diff --git a/easytier-gui/locales/cn.yml b/easytier-gui/locales/cn.yml new file mode 100644 index 0000000..4e6be22 --- /dev/null +++ b/easytier-gui/locales/cn.yml @@ -0,0 +1,55 @@ +network: 网络 +networking_method: 网络方式 +public_server: 公共服务器 +manual: 手动 +standalone: 独立 +virtual_ipv4: 虚拟IPv4地址 +network_name: 网络名称 +network_secret: 网络密码 +public_server_url: 公共服务器地址 +peer_urls: 对等节点地址 +proxy_cidrs: 子网代理CIDR +enable_vpn_portal: 启用VPN门户 +vpn_portal_listen_port: 监听端口 +vpn_portal_client_network: 客户端子网 +advanced_settings: 高级设置 +listener_urls: 监听地址 +rpc_port: RPC端口 +config_network: 配置网络 +running: 运行中 +error_msg: 错误信息 +detail: 详情 +add_new_network: 添加新网络 +del_cur_network: 删除当前网络 +select_network: 选择网络 +network_instances: 网络实例 +instance_id: 实例ID +network_infos: 网络信息 +parse_network_config: 解析网络配置 +retain_network_instance: 保留网络实例 +collect_network_infos: 收集网络信息 +settings: 设置 +exchange_language: Switch to English +exit: 退出 +chips_placeholder: 例如: {0}, 按回车添加 +off_text: 点击关闭 +on_text: 点击开启 +show_config: 显示配置 +close: 关闭 + +my_node_info: 当前节点信息 +peer_count: 已连接 +upload: 上传 +download: 下载 +show_vpn_portal_config: 显示VPN门户配置 +show_event_log: 显示事件日志 +peer_info: 节点信息 +hostname: 主机名 +route_cost: 路由 +latency: 延迟 +upload_bytes: 上传 +download_bytes: 下载 +loss_rate: 丢包率 + +run_network: 运行网络 +stop_network: 停止网络 diff --git a/easytier-gui/locales/en.yml b/easytier-gui/locales/en.yml new file mode 100644 index 0000000..16b4b39 --- /dev/null +++ b/easytier-gui/locales/en.yml @@ -0,0 +1,55 @@ +network: Network +networking_method: Networking Method +public_server: Public Server +manual: Manual +standalone: Standalone +virtual_ipv4: Virtual IPv4 +network_name: Network Name +network_secret: Network Secret +public_server_url: Public Server URL +peer_urls: Peer URLs +proxy_cidrs: Subnet Proxy CIDRs +enable_vpn_portal: Enable VPN Portal +vpn_portal_listen_port: VPN Portal Listen Port +vpn_portal_client_network: Client Sub Network +advanced_settings: Advanced Settings +listener_urls: Listener URLs +rpc_port: RPC Port +config_network: Config Network +running: Running +error_msg: Error Message +detail: Detail +add_new_network: Add New Network +del_cur_network: Delete Current Network +select_network: Select Network +network_instances: Network Instances +instance_id: Instance ID +network_infos: Network Infos +parse_network_config: Parse Network Config +retain_network_instance: Retain Network Instance +collect_network_infos: Collect Network Infos +settings: Settings +exchange_language: 切换中文 +exit: Exit + +chips_placeholder: "e.g: {0}, press Enter to add" +off_text: Press to disable +on_text: Press to enable +show_config: Show Config +close: Close +my_node_info: My Node Info +peer_count: Connected +upload: Upload +download: Download +show_vpn_portal_config: Show VPN Portal Config +show_event_log: Show Event Log +peer_info: Peer Info +route_cost: Route Cost +hostname: Hostname +latency: Latency +upload_bytes: Upload +download_bytes: Download +loss_rate: Loss Rate + +run_network: Run Network +stop_network: Stop Network diff --git a/easytier-gui/src/modules/i18n.ts b/easytier-gui/src/modules/i18n.ts new file mode 100644 index 0000000..e35c81f --- /dev/null +++ b/easytier-gui/src/modules/i18n.ts @@ -0,0 +1,42 @@ +import type { Locale } from 'vue-i18n' +import { createI18n } from 'vue-i18n' + +// Import i18n resources +// https://vitejs.dev/guide/features.html#glob-import +export const i18n = createI18n({ + legacy: false, + locale: '', + fallbackLocale: '', + messages: {}, +}) + +const localesMap = Object.fromEntries( + Object.entries(import.meta.glob('../../locales/*.yml')) + .map(([path, loadLocale]) => [path.match(/([\w-]*)\.yml$/)?.[1], loadLocale]), +) as Record Promise<{ default: Record }>> + +export const availableLocales = Object.keys(localesMap) + +const loadedLanguages: string[] = [] + +function setI18nLanguage(lang: Locale) { + i18n.global.locale.value = lang as any + localStorage.setItem("locale", lang); + return lang +} + +export async function loadLanguageAsync(lang: string): Promise { + // If the same language + if (i18n.global.locale.value === lang) + return setI18nLanguage(lang) + + // If the language was already loaded + if (loadedLanguages.includes(lang)) + return setI18nLanguage(lang) + + // If the language hasn't been loaded yet + const messages = await localesMap[lang]() + i18n.global.setLocaleMessage(lang, messages.default) + loadedLanguages.push(lang) + return setI18nLanguage(lang) +} \ No newline at end of file