xheldon_git-folder-sync/i18n-simple.ts
Xheldon c0948fe13b v1.0.5: Fix Obsidian community plugin feedback issues
- Fix hardcoded .obsidian paths to use app.vault.configDir for better compatibility
- Move inline JavaScript styles to CSS files for better theme adaptability
- Reduce console.log pollution by implementing debug-only logging
- Improve type safety by removing any type casting where possible
- Fix GitHub settings not saving to data.json
- Enhance test URL button to validate both URL format and GitHub token
- Fix debugLog recursive call issue
- Add comprehensive GitHub connection testing with user info and permissions
- Improve user experience with loading states and detailed feedback
- Enhanced code quality to meet Obsidian community plugin standards
2025-08-01 15:35:54 +08:00

514 lines
No EOL
30 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Simplified internationalization system
export type Language = 'zh' | 'en' | 'auto';
// Translation texts
const translations = {
zh: {
// Settings interface
'settings.title': 'Git同步设置',
'settings.language.name': '界面语言',
'settings.language.desc': '选择插件界面显示语言',
'settings.language.auto': '跟随Obsidian',
'settings.github.token.name': 'GitHub Personal Token',
'settings.github.token.desc': '输入你的GitHub Personal Access Token',
'settings.github.token.placeholder': 'ghp_xxxxxxxxxxxx',
'settings.github.repo.name': 'GitHub仓库路径',
'settings.github.repo.desc': '支持两种格式:\n1. https://github.com/用户名/仓库名/路径\n2. 用户名/仓库名/路径',
'settings.github.repo.placeholder': 'https://github.com/Xheldon/git-folder-sync/data/_post',
'settings.ribbon.name': '将插件按钮显示在侧边栏',
'settings.ribbon.desc': '开启后,在左侧边栏显示插件按钮,点击可快速打开设置界面',
'settings.save.name': '保存设置',
'settings.save.desc': '保存当前的配置设置',
'settings.save.button': '保存设置',
'settings.diagnose.name': '诊断Vault文件',
'settings.diagnose.desc': '检查当前Vault中有哪些文件可以同步',
'settings.diagnose.button': '诊断',
'settings.test.url.name': '测试仓库URL',
'settings.test.url.desc': '验证GitHub仓库路径格式是否正确',
'settings.test.url.button': '测试URL',
'settings.test.url.loading': '测试中...',
'settings.sponsor.name': '💖 支持开发者',
'settings.sponsor.desc': '如果这个插件对你有帮助,欢迎请我喝杯咖啡!你的支持是我继续开发的动力。',
'settings.sponsor.button': '💝 PayPal 赞助',
'settings.sponsor.china.label': '🇨🇳 中国大陆捐赠渠道',
'settings.sponsor.section.title': '赞助',
'settings.danger.zone.title': '危险区域',
'settings.init.name': '初始化仓库',
'settings.init.desc': '当本Vault为空的时候可用将远端文件同步到本地',
'settings.init.button': '初始化仓库',
'settings.init.loading': '初始化中...',
'settings.sync.remote.to.local.name': '强制同步远端路径到本地',
'settings.sync.remote.to.local.desc': '将远端的文件一股脑的同步到本地的Vault中同名文件会被覆盖',
'settings.sync.remote.to.local.button': '强制同步到本地',
'settings.sync.remote.to.local.loading': '同步中...',
'settings.sync.local.to.remote.name': '强制同步本地文件到远端',
'settings.sync.local.to.remote.desc': '将本地的Vault中的所有文件同步到远端配置的路径中同名文件会被覆盖',
'settings.sync.local.to.remote.button': '强制同步到远端',
'settings.sync.local.to.remote.loading': '同步中...',
'settings.clear.cache.name': '清空文件缓存',
'settings.clear.cache.desc': '清空所有文件状态缓存下次查看时将重新从GitHub获取',
'settings.clear.cache.button': '清空缓存',
// COS settings
'settings.image.section.title': '图片处理',
'settings.image.enable.name': '启用图片处理功能',
'settings.image.enable.desc': '开启后,粘贴图片时将自动上传到云存储并替换为链接',
'settings.cos.provider.section.title': '云服务商设置',
'settings.image.upload.section.title': '图片上传设置',
'settings.cos.provider.name': '云存储服务商',
'settings.cos.provider.desc': '选择要使用的云对象存储服务商',
'settings.cos.provider.aliyun': '阿里云 OSS',
'settings.cos.provider.tencent': '腾讯云 COS',
'settings.cos.provider.aws': 'AWS S3',
'settings.cos.provider.cloudflare': 'Cloudflare R2',
'settings.cos.secret.id.name': 'Access Key ID / Secret ID',
'settings.cos.secret.id.desc': '云存储服务的访问密钥ID',
'settings.cos.secret.id.placeholder': '输入Access Key ID或Secret ID',
'settings.cos.secret.key.name': 'Access Key Secret / Secret Key',
'settings.cos.secret.key.desc': '云存储服务的访问密钥',
'settings.cos.secret.key.placeholder': '输入Access Key Secret或Secret Key',
'settings.cos.bucket.name': 'Bucket名称',
'settings.cos.bucket.desc': '存储桶名称',
'settings.cos.bucket.placeholder': '输入bucket名称',
'settings.cos.endpoint.name': 'Endpoint',
'settings.cos.endpoint.desc': '服务端点地址仅Cloudflare R2需要',
'settings.cos.endpoint.placeholder': '例如https://accountid.r2.cloudflarestorage.com',
'settings.cos.region.name': 'Region',
'settings.cos.region.desc': '区域设置(所有服务商都需要)',
'settings.cos.region.placeholder': '例如cn-hangzhou、ap-beijing、us-east-1',
'settings.cos.cdn.name': 'CDN地址',
'settings.cos.cdn.desc': 'CDN域名用于生成访问链接',
'settings.cos.cdn.placeholder': '例如https://cdn.example.com',
'settings.cos.keep.local.name': '保留图片在本地',
'settings.cos.keep.local.desc': '上传后是否在本地保留图片副本',
'settings.cos.local.path.name': '本地存储路径',
'settings.cos.local.path.desc': '本地保存图片的目录相对于vault根目录',
'settings.cos.local.path.placeholder': '例如assets',
'settings.cos.upload.path.name': '上传路径模板',
'settings.cos.upload.path.desc': '支持占位符:{PATH}(当前文件路径)、{FILENAME}(文件名)、{FOLDER}(文件夹名)、{YYYY}(年)、{MM}(月)、{DD}(日)',
'settings.cos.upload.path.placeholder': '例如images/{YYYY}/{MM}/{DD}',
'settings.cos.clear.name': '清空当前配置',
'settings.cos.clear.desc': '清空当前选中提供商的所有配置信息',
'settings.cos.clear.button': '清空配置',
'settings.cos.clear.success': '配置已清空',
'settings.cos.test.name': '测试COS配置',
'settings.cos.test.desc': '测试当前COS配置是否可用',
'settings.cos.test.button': '测试连接',
'settings.cos.test.loading': '测试中...',
// Notification messages
'notice.settings.saved': '设置已保存',
'notice.config.required': '请先配置GitHub Token和仓库地址',
'notice.url.required': '请先输入GitHub仓库路径',
'notice.token.required': '请先填写GitHub Token',
'notice.url.test.success': 'URL格式正确',
'notice.url.test.failed': 'URL格式不正确请检查格式。详情请查看控制台。',
'notice.init.error': '初始化仓库时发生错误',
'notice.sync.error': '强制同步时发生错误',
'notice.diagnose.result': 'Vault中共有 {total} 个文件,其中 {syncable} 个可同步。详情请查看控制台。',
'notice.result.with.count': '{message},处理了 {count} 个文件',
'notice.cache.cleared': '已清空 {count} 个文件的缓存',
'notice.cache.clear.error': '清空缓存时发生错误',
// Sync operations
'sync.success': '同步成功: {filename}',
'sync.failed': '同步失败: {message}',
'sync.error': '同步时发生错误',
'pull.success': '拉取成功: {filename}',
'pull.failed': '拉取失败: {message}',
'pull.error': '拉取时发生错误',
// Repository operations
'vault.not.empty': 'Vault不为空无法初始化',
'repo.init.success': '仓库初始化成功',
'repo.init.failed': '仓库初始化失败: {error}',
'force.sync.remote.to.local.success': '强制同步远端到本地成功',
'force.sync.remote.to.local.failed': '强制同步远端到本地失败: {error}',
'no.syncable.files.in.vault': 'Vault中没有可同步的文件',
'force.sync.local.to.remote.success.no.failures': '强制同步本地到远端成功',
'force.sync.local.to.remote.success': '强制同步本地到远端完成,成功: {processed},失败: {failed}',
'force.sync.local.to.remote.failed': '强制同步本地到远端失败: {error}',
// Actions
'actions.sync.current.to.remote': '同步当前文件到远端',
'actions.pull.remote.to.current': '从远端拉取到当前文件',
// Date
'date.today': '今天',
'date.yesterday': '昨天',
// GitHub API Error
'github.api.rate.limit.exceeded': 'GitHub API调用次数已达上限。请等待 {minutes} 分钟后重试。',
'github.api.rate.limit.warning': '⚠️ GitHub API调用次数剩余 {remaining} 次,请谨慎使用。',
'github.api.rate.limit.notice': '速率限制超出',
'github.api.token.invalid': 'GitHub Token无效或已过期。请检查\n1. Token是否正确\n2. Token是否有足够的权限\n3. Token是否已过期',
'github.api.rate.limit.hourly': 'GitHub API调用次数已达上限每小时5000次。\n请等待 {minutes} 分钟后重试或使用GitHub Pro账号获得更高限额。',
'github.api.repo.not.found': '仓库不存在或无访问权限。请检查:\n1. 仓库地址是否正确\n2. Token是否有访问该仓库的权限\n3. 仓库是否为私有仓库',
'github.api.file.conflict': '文件冲突。远程文件已被其他人修改。\n请先同步远程更改然后重试。',
'github.api.validation.failed': 'GitHub API验证失败。请检查\n1. 文件路径是否正确\n2. 文件内容是否符合要求\n3. 仓库权限设置',
'github.api.server.error': 'GitHub服务器错误{status})。请稍后重试。',
'github.api.network.error': '网络连接错误。请检查:\n1. 网络连接是否正常\n2. 防火墙设置\n3. 代理配置',
'github.api.timeout.error': '请求超时。请检查网络连接或稍后重试。',
'github.api.unknown.error': '未知错误:{message}',
'github.api.access.denied': 'GitHub访问被拒绝。可能原因\n1. Token权限不足\n2. 仓库为私有且Token无访问权限\n3. 仓库不存在',
'github.api.resource.not.found': '资源未找到。请检查:\n1. 仓库路径是否正确\n2. 文件路径是否存在\n3. Token是否有访问该仓库的权限',
'github.api.file.conflict.detailed': '文件冲突。可能原因:\n1. 文件在远程已被修改\n2. 请先从远端同步最新版本',
'github.api.invalid.request': '请求参数无效。请检查:\n1. 文件内容是否过大(>100MB\n2. 文件路径格式是否正确',
'github.api.server.error.detailed': 'GitHub服务器错误请稍后重试。如果问题持续存在请检查GitHub服务状态。',
'github.api.error.with.status': 'GitHub API错误 ({status}): {message}',
'github.api.network.failed': '网络连接失败。请检查:\n1. 网络连接是否正常\n2. 是否能访问github.com\n3. 防火墙或代理设置',
'github.api.timeout.detailed': '请求超时。请检查网络连接或稍后重试。',
'github.api.operation.failed': '操作失败: {message}',
'github.api.retry.hint': '💡 提示:这是临时性错误,稍后可以重试',
'github.api.invalid.url.format': '无效的仓库URL格式',
'github.api.rate.limit.exceeded.short': 'GitHub API调用次数已达上限请稍后重试',
'github.api.file.upload.success': '文件上传成功',
'github.api.all.files.download.success': '所有文件下载成功',
'github.api.connection.test.success': '✅ 连接测试成功!\n👤 用户: {user}\n📁 仓库: {repo}\n🔑 权限: {permissions}',
// Status bar
'status.bar.checking': '检查中...',
'status.bar.sync': '同步',
'status.bar.rate.limit': 'API限制: 等待{minutes}分钟',
'status.bar.last.modified': '上次更新: {date}',
'status.bar.not.published': '未发布',
'status.bar.check.failed': '检查失败',
'status.bar.not.configured': '未配置',
'status.bar.local.modified': '本地已修改',
'status.bar.synced': '已同步',
// Plugin info
'plugin.name': 'Git同步',
'command.show.sync.menu': '显示同步菜单',
// Test URL results
'test.url.user': '用户',
'test.url.repo': '仓库',
'test.url.path': '路径',
'test.url.root': '根目录',
// Path info
'path.info.empty': '请输入GitHub仓库路径以查看同步目标',
'path.info.sync.to': '当前 Vault 内容将同步到 {owner}/{repo} 仓库',
'path.info.folder': ' 的 {path} 文件夹下',
'path.info.root': ' 的根目录下',
'path.info.error': '路径格式不正确,请使用: https://github.com/用户名/仓库名/路径 或 用户名/仓库名/路径',
// COS upload messages
'cos.upload.success': '图片上传成功',
'cos.upload.failed': '图片上传失败: {error}',
'cos.upload.uploading': '正在上传图片...',
'cos.upload.no.config': '图片处理功能已启用,但需要配置云存储或本地存储路径',
'cos.test.success': 'COS配置测试成功',
'cos.test.failed': 'COS配置测试失败{error}',
'cos.error.unsupported.provider': '不支持的云存储服务商:{provider}',
'cos.error.upload.failed': '上传失败:{error}',
'cos.error.aliyun.upload.failed': '阿里云OSS上传失败{status}{error}',
'cos.error.tencent.upload.failed': '腾讯云COS上传失败{status}{error}',
'cos.error.aws.upload.failed': 'AWS S3上传失败{status}{error}',
'cos.error.cloudflare.upload.failed': 'Cloudflare R2上传失败{status}{error}',
'cos.error.config.invalid': 'COS配置不完整请检查配置项',
'cos.paste.placeholder': '正在上传 {filename}...',
},
en: {
// Settings interface
'settings.title': 'Git Folder Sync Settings',
'settings.language.name': 'Interface Language',
'settings.language.desc': 'Select the display language for the plugin interface',
'settings.language.auto': 'Follow Obsidian',
'settings.github.token.name': 'GitHub Personal Token',
'settings.github.token.desc': 'Enter your GitHub Personal Access Token',
'settings.github.token.placeholder': 'ghp_xxxxxxxxxxxx',
'settings.github.repo.name': 'GitHub Repository Path',
'settings.github.repo.desc': 'Supports two formats:\n1. https://github.com/username/repo/path\n2. username/repo/path',
'settings.github.repo.placeholder': 'https://github.com/Xheldon/git-folder-sync/data/_post',
'settings.ribbon.name': 'Show plugin button in sidebar',
'settings.ribbon.desc': 'When enabled, display plugin button in left sidebar for quick access to settings',
'settings.save.name': 'Save Settings',
'settings.save.desc': 'Save current configuration settings',
'settings.save.button': 'Save Settings',
'settings.diagnose.name': 'Diagnose Vault Files',
'settings.diagnose.desc': 'Check which files in current Vault can be synchronized',
'settings.diagnose.button': 'Diagnose',
'settings.test.url.name': 'Test Repository URL',
'settings.test.url.desc': 'Verify if GitHub repository path format is correct',
'settings.test.url.button': 'Test URL',
'settings.test.url.loading': 'Testing...',
'settings.sponsor.name': '💖 Support Developer',
'settings.sponsor.desc': 'If this plugin helps you, consider buying me a coffee! Your support motivates me to continue development.',
'settings.sponsor.button': '💝 PayPal Sponsor',
'settings.sponsor.section.title': 'Sponsor',
'settings.danger.zone.title': 'Danger Zone',
'settings.init.name': 'Initialize Repository',
'settings.init.desc': 'Available when Vault is empty, sync remote files to local',
'settings.init.button': 'Initialize Repository',
'settings.init.loading': 'Initializing...',
'settings.sync.remote.to.local.name': 'Force Sync Remote to Local',
'settings.sync.remote.to.local.desc': 'Sync all remote files to local Vault, existing files will be overwritten',
'settings.sync.remote.to.local.button': 'Force Sync to Local',
'settings.sync.remote.to.local.loading': 'Syncing...',
'settings.sync.local.to.remote.name': 'Force Sync Local to Remote',
'settings.sync.local.to.remote.desc': 'Sync all local Vault files to remote repository, existing files will be overwritten',
'settings.sync.local.to.remote.button': 'Force Sync to Remote',
'settings.sync.local.to.remote.loading': 'Syncing...',
'settings.clear.cache.name': 'Clear File Cache',
'settings.clear.cache.desc': 'Clear all file status cache, will fetch from GitHub on next view',
'settings.clear.cache.button': 'Clear Cache',
// COS settings
'settings.image.section.title': 'Image Processing',
'settings.image.enable.name': 'Enable Image Processing',
'settings.image.enable.desc': 'When enabled, images pasted will be automatically uploaded to cloud storage and replaced with links',
'settings.cos.provider.section.title': 'Cloud Provider Settings',
'settings.image.upload.section.title': 'Image Upload Settings',
'settings.cos.provider.name': 'Cloud Storage Provider',
'settings.cos.provider.desc': 'Select the cloud object storage service to use',
'settings.cos.provider.aliyun': 'Aliyun OSS',
'settings.cos.provider.tencent': 'Tencent COS',
'settings.cos.provider.aws': 'AWS S3',
'settings.cos.provider.cloudflare': 'Cloudflare R2',
'settings.cos.secret.id.name': 'Access Key ID / Secret ID',
'settings.cos.secret.id.desc': 'Access key ID for cloud storage service',
'settings.cos.secret.id.placeholder': 'Enter Access Key ID or Secret ID',
'settings.cos.secret.key.name': 'Access Key Secret / Secret Key',
'settings.cos.secret.key.desc': 'Access key secret for cloud storage service',
'settings.cos.secret.key.placeholder': 'Enter Access Key Secret or Secret Key',
'settings.cos.bucket.name': 'Bucket Name',
'settings.cos.bucket.desc': 'Storage bucket name',
'settings.cos.bucket.placeholder': 'Enter bucket name',
'settings.cos.endpoint.name': 'Endpoint',
'settings.cos.endpoint.desc': 'Service endpoint address (only required for Cloudflare R2)',
'settings.cos.endpoint.placeholder': 'e.g.: https://accountid.r2.cloudflarestorage.com',
'settings.cos.region.name': 'Region',
'settings.cos.region.desc': 'Region setting (required for all providers)',
'settings.cos.region.placeholder': 'e.g.: cn-hangzhou, ap-beijing, us-east-1',
'settings.cos.cdn.name': 'CDN URL',
'settings.cos.cdn.desc': 'CDN domain for generating access links',
'settings.cos.cdn.placeholder': 'e.g.: https://cdn.example.com',
'settings.cos.keep.local.name': 'Keep Images Locally',
'settings.cos.keep.local.desc': 'Whether to keep a local copy of images after upload',
'settings.cos.local.path.name': 'Local Storage Path',
'settings.cos.local.path.desc': 'Directory to save images locally (relative to vault root)',
'settings.cos.local.path.placeholder': 'e.g.: assets',
'settings.cos.upload.path.name': 'Upload Path Template',
'settings.cos.upload.path.desc': 'Supports placeholders: {PATH} (current file path), {FILENAME} (file name), {FOLDER} (folder name), {YYYY} (year), {MM} (month), {DD} (day)',
'settings.cos.upload.path.placeholder': 'e.g.: images/{YYYY}/{MM}/{DD}',
'settings.cos.clear.name': 'Clear Current Configuration',
'settings.cos.clear.desc': 'Clear all configuration for the currently selected provider',
'settings.cos.clear.button': 'Clear Config',
'settings.cos.clear.success': 'Configuration cleared',
'settings.cos.test.name': 'Test COS Configuration',
'settings.cos.test.desc': 'Test if current COS configuration is available',
'settings.cos.test.button': 'Test Connection',
'settings.cos.test.loading': 'Testing...',
// Notification messages
'notice.settings.saved': 'Settings saved',
'notice.config.required': 'Please configure GitHub Token and repository address first',
'notice.url.required': 'Please enter GitHub repository path first',
'notice.token.required': 'Please enter GitHub Token first',
'notice.url.test.success': 'URL format is correct!',
'notice.url.test.failed': 'URL format is incorrect, please check format. See console for details.',
'notice.init.error': 'Error occurred during repository initialization',
'notice.sync.error': 'Error occurred during force sync',
'notice.diagnose.result': 'Vault has {total} files in total, {syncable} can be synced. See console for details.',
'notice.result.with.count': '{message}, processed {count} files',
'notice.cache.cleared': 'Cleared cache for {count} files',
'notice.cache.clear.error': 'Error occurred while clearing cache',
// Sync operations
'sync.success': 'Sync success: {filename}',
'sync.failed': 'Sync failed: {message}',
'sync.error': 'Error occurred during sync',
'pull.success': 'Pull success: {filename}',
'pull.failed': 'Pull failed: {message}',
'pull.error': 'Error occurred during pull',
// Repository operations
'vault.not.empty': 'Vault is not empty, cannot initialize',
'repo.init.success': 'Repository initialized successfully',
'repo.init.failed': 'Repository initialization failed: {error}',
'force.sync.remote.to.local.success': 'Force sync remote to local success',
'force.sync.remote.to.local.failed': 'Force sync remote to local failed: {error}',
'no.syncable.files.in.vault': 'No syncable files in vault',
'force.sync.local.to.remote.success.no.failures': 'Force sync local to remote success',
'force.sync.local.to.remote.success': 'Force sync local to remote completed, success: {processed}, failed: {failed}',
'force.sync.local.to.remote.failed': 'Force sync local to remote failed: {error}',
// Actions
'actions.sync.current.to.remote': 'Sync current file to remote',
'actions.pull.remote.to.current': 'Pull remote to current file',
// Date
'date.today': 'Today',
'date.yesterday': 'Yesterday',
// GitHub API errors
'github.api.rate.limit.exceeded': 'GitHub API rate limit exceeded. Please wait {minutes} minutes before retrying.',
'github.api.rate.limit.warning': '⚠️ GitHub API calls remaining: {remaining}. Please use carefully.',
'github.api.rate.limit.notice': 'Rate limit exceeded',
'github.api.token.invalid': 'GitHub Token is invalid or expired. Please check:\n1. Token is correct\n2. Token has sufficient permissions\n3. Token has not expired',
'github.api.rate.limit.hourly': 'GitHub API hourly rate limit exceeded (5000 per hour).\nPlease wait {minutes} minutes or use GitHub Pro for higher limits.',
'github.api.repo.not.found': 'Repository not found or no access permission. Please check:\n1. Repository URL is correct\n2. Token has access to this repository\n3. Repository is not private',
'github.api.file.conflict': 'File conflict. Remote file has been modified by others.\nPlease sync remote changes first, then retry.',
'github.api.validation.failed': 'GitHub API validation failed. Please check:\n1. File path is correct\n2. File content meets requirements\n3. Repository permission settings',
'github.api.server.error': 'GitHub server error ({status}). Please retry later.',
'github.api.network.error': 'Network connection error. Please check:\n1. Network connection is normal\n2. Firewall settings\n3. Proxy configuration',
'github.api.timeout.error': 'Request timeout. Please check network connection or retry later.',
'github.api.unknown.error': 'Unknown error: {message}',
'github.api.access.denied': 'GitHub access denied. Possible reasons:\n1. Insufficient token permissions\n2. Repository is private and token has no access\n3. Repository does not exist',
'github.api.resource.not.found': 'Resource not found. Please check:\n1. Repository path is correct\n2. File path exists\n3. Token has access to this repository',
'github.api.file.conflict.detailed': 'File conflict. Possible reasons:\n1. File has been modified remotely\n2. Please sync from remote first',
'github.api.invalid.request': 'Invalid request parameters. Please check:\n1. File content is not too large (>100MB)\n2. File path format is correct',
'github.api.server.error.detailed': 'GitHub server error, please retry later. If problem persists, check GitHub service status.',
'github.api.error.with.status': 'GitHub API error ({status}): {message}',
'github.api.network.failed': 'Network connection failed. Please check:\n1. Network connection is normal\n2. Can access github.com\n3. Firewall or proxy settings',
'github.api.timeout.detailed': 'Request timeout. Please check network connection or retry later.',
'github.api.operation.failed': 'Operation failed: {message}',
'github.api.retry.hint': '💡 Tip: This is a temporary error, you can retry later',
'github.api.invalid.url.format': 'Invalid repository URL format',
'github.api.rate.limit.exceeded.short': 'GitHub API rate limit exceeded, please retry later',
'github.api.file.upload.success': 'File uploaded successfully',
'github.api.all.files.download.success': 'All files downloaded successfully',
'github.api.connection.test.success': '✅ Connection test successful!\n👤 User: {user}\n📁 Repository: {repo}\n🔑 Permissions: {permissions}',
// Status bar
'status.bar.checking': 'Checking...',
'status.bar.sync': 'Sync',
'status.bar.rate.limit': 'API limit: wait {minutes} minutes',
'status.bar.last.modified': 'Last modified: {date}',
'status.bar.not.published': 'Not published',
'status.bar.check.failed': 'Check failed',
'status.bar.not.configured': 'Not configured',
'status.bar.local.modified': 'Local modified',
'status.bar.synced': 'Synced',
// Plugin info
'plugin.name': 'Git Folder Sync',
'command.show.sync.menu': 'Show Sync Menu',
// Test URL results
'test.url.user': 'User',
'test.url.repo': 'Repo',
'test.url.path': 'Path',
'test.url.root': 'Root',
// Path info
'path.info.empty': 'Enter GitHub repository path to view sync target',
'path.info.sync.to': 'Current Vault content will sync to {owner}/{repo} repository',
'path.info.folder': ' under {path} folder',
'path.info.root': ' under root directory',
'path.info.error': 'Path format is incorrect, please use: https://github.com/username/repo/path or username/repo/path',
// COS upload messages
'cos.upload.success': 'Image uploaded successfully',
'cos.upload.failed': 'Image upload failed: {error}',
'cos.upload.uploading': 'Uploading image...',
'cos.upload.no.config': 'Image processing is enabled, but cloud storage or local storage path needs to be configured',
'cos.test.success': 'COS configuration test successful',
'cos.test.failed': 'COS configuration test failed: {error}',
'cos.error.unsupported.provider': 'Unsupported cloud storage provider: {provider}',
'cos.error.upload.failed': 'Upload failed: {error}',
'cos.error.aliyun.upload.failed': 'Aliyun OSS upload failed ({status}): {error}',
'cos.error.tencent.upload.failed': 'Tencent COS upload failed ({status}): {error}',
'cos.error.aws.upload.failed': 'AWS S3 upload failed ({status}): {error}',
'cos.error.cloudflare.upload.failed': 'Cloudflare R2 upload failed ({status}): {error}',
'cos.error.config.invalid': 'COS configuration is incomplete, please check settings',
'cos.paste.placeholder': 'Uploading {filename}...',
}
};
// Current language
let currentLanguage: Language = 'auto';
// Extended window interface for type safety
interface ExtendedWindow extends Window {
app?: {
vault?: {
adapter?: {
path?: {
locale?: string;
};
};
};
};
moment?: {
locale(): string;
};
}
// Detect Obsidian's language settings
function detectObsidianLanguage(): 'zh' | 'en' {
// Check Obsidian's language settings - more accurate method
const obsidianLang = localStorage.getItem('language') ||
(window as ExtendedWindow).app?.vault?.adapter?.path?.locale ||
(window as ExtendedWindow).moment?.locale();
// Check browser language
const browserLang = navigator.language || navigator.languages?.[0] || 'en';
// If it's Chinese-related language code, return Chinese
if (obsidianLang?.includes('zh') || browserLang.startsWith('zh')) {
return 'zh';
}
// Default return English
return 'en';
}
// Get the actual language used
export function getActualLanguage(): 'zh' | 'en' {
if (currentLanguage === 'auto') {
return detectObsidianLanguage();
}
return currentLanguage as 'zh' | 'en';
}
// Set current language
export function setLanguage(language: Language): void {
currentLanguage = language;
}
// Get current language
export function getCurrentLanguage(): Language {
return currentLanguage;
}
// Translation function
export function t(key: string, params?: Record<string, string | number>): string {
const actualLang = getActualLanguage();
const translation = translations[actualLang][key as keyof typeof translations['zh']];
if (!translation) {
console.warn(`Translation missing for key: ${key}`);
return key;
}
// If there are parameters, perform replacement
if (params) {
return Object.entries(params).reduce((text, [paramKey, paramValue]) => {
return text.replace(new RegExp(`\\{${paramKey}\\}`, 'g'), String(paramValue));
}, translation);
}
return translation;
}
// Get all supported languages
export function getSupportedLanguages(): Array<{ value: Language; label: string }> {
// Detect system language for displaying content in parentheses
const detectedLang = detectObsidianLanguage();
const detectedLangText = detectedLang === 'zh' ? '中文' : 'English';
// Determine the display text for "Follow" based on current plugin language
const currentLang = getActualLanguage();
const followText = currentLang === 'zh' ? '跟随Obsidian' : 'Follow Obsidian';
const autoLabel = `${followText} (${detectedLangText})`;
return [
{ value: 'auto', label: autoLabel },
{ value: 'zh', label: '中文' },
{ value: 'en', label: 'English' },
];
}