mirror of
https://github.com/veeso/termscp.git
synced 2026-07-02 12:44:12 +02:00
feat(site): i18n string resolver with en fallback
This commit is contained in:
34
site/src/i18n/en.json
Normal file
34
site/src/i18n/en.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"nav.home": "Home",
|
||||
"nav.install": "Install",
|
||||
"nav.manual": "User manual",
|
||||
"nav.github": "GitHub",
|
||||
"hero.tabs": "termscp — {host} (sftp) connected",
|
||||
"hero.local": "/home/veeso (local)",
|
||||
"hero.remote": "/var/www (remote)",
|
||||
"hero.status": "↹ switch · ↑↓ move · ↵ open · SPACE transfer",
|
||||
"hero.title": "The dual-pane explorer for your terminal",
|
||||
"hero.subtitle": "Local left, remote right. Transfer, sync, edit — never leave the keyboard.",
|
||||
"hero.kicker": "// terminal file transfer",
|
||||
"cta.install": "Install termscp →",
|
||||
"cta.manual": "User manual",
|
||||
"features.heading": "Why termscp",
|
||||
"features.handy.title": "Handy UI",
|
||||
"features.handy.body": "Explore and operate on the remote and local file system with a handy UI.",
|
||||
"features.cross.title": "Cross platform",
|
||||
"features.cross.body": "Runs on Windows, macOS, Linux and BSD.",
|
||||
"features.custom.title": "Customizable",
|
||||
"features.custom.body": "Customize the explorer, the text editor and default options.",
|
||||
"features.bookmarks.title": "Bookmarks",
|
||||
"features.bookmarks.body": "Connect to favourite hosts via bookmarks and recent connections.",
|
||||
"features.security.title": "Security first",
|
||||
"features.security.body": "Store passwords in your operating system key vault.",
|
||||
"features.performance.title": "Eye on performance",
|
||||
"features.performance.body": "Built with an eye on performance to keep CPU usage low.",
|
||||
"protocols.heading": "Speaks every protocol",
|
||||
"install.heading": "Install termscp",
|
||||
"install.subtitle": "Pick your platform. One command and you're in.",
|
||||
"footer.support": "Support me",
|
||||
"footer.rights": "Released under the MIT license.",
|
||||
"lang.label": "Language"
|
||||
}
|
||||
34
site/src/i18n/es.json
Normal file
34
site/src/i18n/es.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"nav.home": "Inicio",
|
||||
"nav.install": "Instalar",
|
||||
"nav.manual": "Manual de usuario",
|
||||
"nav.github": "GitHub",
|
||||
"hero.tabs": "termscp — {host} (sftp) conectado",
|
||||
"hero.local": "/home/veeso (local)",
|
||||
"hero.remote": "/var/www (remoto)",
|
||||
"hero.status": "↹ cambiar · ↑↓ mover · ↵ abrir · ESPACIO transferir",
|
||||
"hero.title": "El explorador de doble panel para tu terminal",
|
||||
"hero.subtitle": "Local a la izquierda, remoto a la derecha. Transfiere, sincroniza, edita — sin soltar el teclado.",
|
||||
"hero.kicker": "// transferencia de archivos en terminal",
|
||||
"cta.install": "Instalar termscp →",
|
||||
"cta.manual": "Manual de usuario",
|
||||
"features.heading": "Por qué termscp",
|
||||
"features.handy.title": "Interfaz práctica",
|
||||
"features.handy.body": "Explora y opera en el sistema de archivos remoto y local con una interfaz práctica.",
|
||||
"features.cross.title": "Multiplataforma",
|
||||
"features.cross.body": "Funciona en Windows, macOS, Linux y BSD.",
|
||||
"features.custom.title": "Personalizable",
|
||||
"features.custom.body": "Personaliza el explorador, el editor de texto y las opciones predeterminadas.",
|
||||
"features.bookmarks.title": "Marcadores",
|
||||
"features.bookmarks.body": "Conéctate a tus hosts favoritos mediante marcadores y conexiones recientes.",
|
||||
"features.security.title": "Seguridad primero",
|
||||
"features.security.body": "Guarda tus contraseñas en la bóveda de claves de tu sistema operativo.",
|
||||
"features.performance.title": "Ojo en el rendimiento",
|
||||
"features.performance.body": "Desarrollado teniendo en cuenta el rendimiento para mantener bajo el uso de CPU.",
|
||||
"protocols.heading": "Habla todos los protocolos",
|
||||
"install.heading": "Instalar termscp",
|
||||
"install.subtitle": "Elige tu plataforma. Un comando y listo.",
|
||||
"footer.support": "Apóyame",
|
||||
"footer.rights": "Publicado bajo la licencia MIT.",
|
||||
"lang.label": "Idioma"
|
||||
}
|
||||
33
site/src/i18n/fr.json
Normal file
33
site/src/i18n/fr.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"nav.home": "Accueil",
|
||||
"nav.install": "Installer",
|
||||
"nav.github": "GitHub",
|
||||
"hero.tabs": "termscp — {host} (sftp) connecté",
|
||||
"hero.local": "/home/veeso (local)",
|
||||
"hero.remote": "/var/www (distant)",
|
||||
"hero.status": "↹ basculer · ↑↓ déplacer · ↵ ouvrir · ESPACE transférer",
|
||||
"hero.title": "L'explorateur à deux panneaux pour votre terminal",
|
||||
"hero.subtitle": "Local à gauche, distant à droite. Transférez, synchronisez, éditez — sans quitter le clavier.",
|
||||
"hero.kicker": "// transfert de fichiers en terminal",
|
||||
"cta.install": "Installer termscp →",
|
||||
"cta.manual": "Manuel d'utilisateur",
|
||||
"features.heading": "Pourquoi termscp",
|
||||
"features.handy.title": "Interface pratique",
|
||||
"features.handy.body": "Explorez et utilisez le système de fichiers distant et local avec une interface pratique.",
|
||||
"features.cross.title": "Multi-plateforme",
|
||||
"features.cross.body": "Fonctionne sur Windows, macOS, Linux et BSD.",
|
||||
"features.custom.title": "Personnalisable",
|
||||
"features.custom.body": "Personnalisez l'explorateur, l'éditeur de texte et les options par défaut.",
|
||||
"features.bookmarks.title": "Signets",
|
||||
"features.bookmarks.body": "Connectez-vous à vos hôtes préférés via des signets et des connexions récentes.",
|
||||
"features.security.title": "Sécurité avant tout",
|
||||
"features.security.body": "Enregistrez vos mots de passe dans le coffre-fort de votre système.",
|
||||
"features.performance.title": "Regard sur les performances",
|
||||
"features.performance.body": "Développé en gardant un œil sur les performances pour éviter une utilisation élevée du processeur.",
|
||||
"protocols.heading": "Parle tous les protocoles",
|
||||
"install.heading": "Installer termscp",
|
||||
"install.subtitle": "Choisissez votre plateforme. Une commande et c'est parti.",
|
||||
"footer.support": "Me soutenir",
|
||||
"footer.rights": "Publié sous licence MIT.",
|
||||
"lang.label": "Langue"
|
||||
}
|
||||
34
site/src/i18n/it.json
Normal file
34
site/src/i18n/it.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"nav.home": "Home",
|
||||
"nav.install": "Installa",
|
||||
"nav.manual": "Manuale utente",
|
||||
"nav.github": "GitHub",
|
||||
"hero.tabs": "termscp — {host} (sftp) connesso",
|
||||
"hero.local": "/home/veeso (locale)",
|
||||
"hero.remote": "/var/www (remoto)",
|
||||
"hero.status": "↹ cambia · ↑↓ muovi · ↵ apri · SPAZIO trasferisci",
|
||||
"hero.title": "L'explorer a doppio pannello per il tuo terminale",
|
||||
"hero.subtitle": "Locale a sinistra, remoto a destra. Trasferisci, sincronizza, modifica — senza mai lasciare la tastiera.",
|
||||
"hero.kicker": "// file transfer da terminale",
|
||||
"cta.install": "Installa termscp →",
|
||||
"cta.manual": "Manuale utente",
|
||||
"features.heading": "Perché termscp",
|
||||
"features.handy.title": "UI ergonomica",
|
||||
"features.handy.body": "Naviga e lavora sul file system remoto e locale attraverso una UI di facile utilizzo.",
|
||||
"features.cross.title": "Multi piattaforma",
|
||||
"features.cross.body": "Gira su Windows, macOS, Linux e BSD.",
|
||||
"features.custom.title": "Personalizzabile",
|
||||
"features.custom.body": "Personalizza l'explorer, l'editor di testo e le opzioni predefinite.",
|
||||
"features.bookmarks.title": "Preferiti",
|
||||
"features.bookmarks.body": "Connettiti agli host preferiti tramite preferiti e connessioni recenti.",
|
||||
"features.security.title": "Sicurezza in prima classe",
|
||||
"features.security.body": "Salva le password nel vault del tuo sistema operativo.",
|
||||
"features.performance.title": "Focus sulle performance",
|
||||
"features.performance.body": "Sviluppato con un occhio alle performance per mantenere basso l'uso della CPU.",
|
||||
"protocols.heading": "Parla ogni protocollo",
|
||||
"install.heading": "Installa termscp",
|
||||
"install.subtitle": "Scegli la tua piattaforma. Un comando e sei dentro.",
|
||||
"footer.support": "Supportami",
|
||||
"footer.rights": "Rilasciato sotto licenza MIT.",
|
||||
"lang.label": "Lingua"
|
||||
}
|
||||
29
site/src/i18n/ui.test.ts
Normal file
29
site/src/i18n/ui.test.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { useTranslations, locales, defaultLocale } from "./ui";
|
||||
|
||||
describe("i18n", () => {
|
||||
it("exposes the five supported locales with en default", () => {
|
||||
expect(locales).toEqual(["en", "zh-CN", "it", "fr", "es"]);
|
||||
expect(defaultLocale).toBe("en");
|
||||
});
|
||||
|
||||
it("resolves a key in the requested locale", () => {
|
||||
const t = useTranslations("it");
|
||||
expect(t("nav.install")).toBe("Installa");
|
||||
});
|
||||
|
||||
it("falls back to en when a key is missing in the locale", () => {
|
||||
const t = useTranslations("fr");
|
||||
expect(t("nav.manual")).toBe("User manual");
|
||||
});
|
||||
|
||||
it("returns the key itself when missing everywhere", () => {
|
||||
const t = useTranslations("en");
|
||||
expect(t("does.not.exist")).toBe("does.not.exist");
|
||||
});
|
||||
|
||||
it("interpolates {vars}", () => {
|
||||
const t = useTranslations("en");
|
||||
expect(t("hero.tabs", { host: "1.2.3.4" })).toContain("1.2.3.4");
|
||||
});
|
||||
});
|
||||
35
site/src/i18n/ui.ts
Normal file
35
site/src/i18n/ui.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import en from "./en.json";
|
||||
import zhCN from "./zh-CN.json";
|
||||
import it from "./it.json";
|
||||
import fr from "./fr.json";
|
||||
import es from "./es.json";
|
||||
|
||||
export const locales = ["en", "zh-CN", "it", "fr", "es"] as const;
|
||||
export type Locale = (typeof locales)[number];
|
||||
export const defaultLocale: Locale = "en";
|
||||
|
||||
const dictionaries: Record<Locale, Record<string, string>> = {
|
||||
en: en as Record<string, string>,
|
||||
"zh-CN": zhCN as Record<string, string>,
|
||||
it: it as Record<string, string>,
|
||||
fr: fr as Record<string, string>,
|
||||
es: es as Record<string, string>,
|
||||
};
|
||||
|
||||
export function isLocale(value: string): value is Locale {
|
||||
return (locales as readonly string[]).includes(value);
|
||||
}
|
||||
|
||||
/** Resolve a translator for `locale`, falling back to en, then to the key. */
|
||||
export function useTranslations(locale: Locale) {
|
||||
const dict = dictionaries[locale] ?? dictionaries[defaultLocale];
|
||||
return (key: string, vars?: Record<string, string>): string => {
|
||||
let value = dict[key] ?? dictionaries[defaultLocale][key] ?? key;
|
||||
if (vars) {
|
||||
for (const [k, v] of Object.entries(vars)) {
|
||||
value = value.replaceAll(`{${k}}`, v);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
34
site/src/i18n/zh-CN.json
Normal file
34
site/src/i18n/zh-CN.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"nav.home": "主页",
|
||||
"nav.install": "安装",
|
||||
"nav.manual": "用户手册",
|
||||
"nav.github": "GitHub",
|
||||
"hero.tabs": "termscp — {host} (sftp) 已连接",
|
||||
"hero.local": "/home/veeso (本地)",
|
||||
"hero.remote": "/var/www (远程)",
|
||||
"hero.status": "↹ 切换 · ↑↓ 移动 · ↵ 打开 · 空格 传输",
|
||||
"hero.title": "为你的终端打造的双栏文件浏览器",
|
||||
"hero.subtitle": "左边本地,右边远程。传输、同步、编辑 — 始终不离键盘。",
|
||||
"hero.kicker": "// 终端文件传输",
|
||||
"cta.install": "安装 termscp →",
|
||||
"cta.manual": "用户手册",
|
||||
"features.heading": "为什么选择 termscp",
|
||||
"features.handy.title": "方便的用户界面",
|
||||
"features.handy.body": "使用方便的 UI 在远程和本地文件系统上探索和操作。",
|
||||
"features.cross.title": "跨平台",
|
||||
"features.cross.body": "在 Windows、macOS、Linux 和 BSD 上运行。",
|
||||
"features.custom.title": "可定制",
|
||||
"features.custom.body": "自定义文件浏览器、文本编辑器和默认选项。",
|
||||
"features.bookmarks.title": "书签",
|
||||
"features.bookmarks.body": "通过书签和最近的连接连接到你最喜欢的主机。",
|
||||
"features.security.title": "安全第一",
|
||||
"features.security.body": "将你的密码保存到操作系统的密钥保管库中。",
|
||||
"features.performance.title": "关注性能",
|
||||
"features.performance.body": "在开发时关注性能,以保持较低的 CPU 使用率。",
|
||||
"protocols.heading": "支持各种协议",
|
||||
"install.heading": "安装 termscp",
|
||||
"install.subtitle": "选择你的平台。一条命令即可上手。",
|
||||
"footer.support": "支持我",
|
||||
"footer.rights": "基于 MIT 许可证发布。",
|
||||
"lang.label": "语言"
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
|
||||
5
site/vitest.config.ts
Normal file
5
site/vitest.config.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: { include: ["src/**/*.test.ts", "scripts/**/*.test.ts"] },
|
||||
});
|
||||
Reference in New Issue
Block a user