Squash merge feat/expo-app: app-expo, .cursor, workflows, package.json, .husky; remove app-android, app-ios, react-app
This commit is contained in:
10
app-expo/src/i18n/generated/i18next.d.ts
vendored
Normal file
10
app-expo/src/i18n/generated/i18next.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
// This file is automatically generated by i18next-cli, because it was not existing. You can edit it based on your needs: https://www.i18next.com/overview/typescript#custom-type-options
|
||||
import Resources from './resources.ts';
|
||||
|
||||
declare module 'i18next' {
|
||||
interface CustomTypeOptions {
|
||||
enableSelector: false;
|
||||
defaultNS: 'common';
|
||||
resources: Resources;
|
||||
}
|
||||
}
|
||||
158
app-expo/src/i18n/generated/resources.ts
Normal file
158
app-expo/src/i18n/generated/resources.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
// This file is automatically generated by i18next-cli. Do not edit manually.
|
||||
interface Resources {
|
||||
app: {
|
||||
languages: {
|
||||
en: 'English';
|
||||
system: 'System';
|
||||
zh: 'Chinese';
|
||||
};
|
||||
name: 'Life Echo';
|
||||
tabs: {
|
||||
conversations: 'Chats';
|
||||
explore: 'Explore';
|
||||
home: 'Home';
|
||||
memoir: 'Memoir';
|
||||
profile: 'Profile';
|
||||
};
|
||||
theme: {
|
||||
brand: 'Brand';
|
||||
default: 'Default';
|
||||
};
|
||||
};
|
||||
auth: {
|
||||
login: {
|
||||
codeLabel: 'Verification Code';
|
||||
getCode: 'Get Code';
|
||||
getCodeCountdown: 'Retry in {{seconds}}s';
|
||||
networkError: 'Network error. Please try again later.';
|
||||
phoneLabel: 'Phone Number';
|
||||
phonePlaceholder: 'Enter your phone number';
|
||||
privacyPolicy: 'Privacy Policy';
|
||||
submit: 'Login';
|
||||
termsAnd: 'and';
|
||||
termsIntro: 'I agree to the';
|
||||
termsRequired: 'Please agree to the User Agreement and Privacy Policy first';
|
||||
termsRequiredConfirm: 'OK';
|
||||
termsRequiredTitle: 'Agreement Required';
|
||||
userAgreement: 'User Agreement';
|
||||
welcomeSubtitle: 'Some lives grow richer the more you savor them.';
|
||||
welcomeTitle: 'Welcome back';
|
||||
};
|
||||
};
|
||||
common: {
|
||||
chapterLabel: '';
|
||||
chapterReading: {
|
||||
backgroundColor: '';
|
||||
bgPureWhite: '';
|
||||
bgSepia: '';
|
||||
close: '';
|
||||
fontSize: '';
|
||||
readingSettings: '';
|
||||
typography: '';
|
||||
};
|
||||
continueWriting: '';
|
||||
docs: 'Docs';
|
||||
emptySubtitle: '';
|
||||
emptyTitle: '';
|
||||
readMemory: '';
|
||||
startChapter: '';
|
||||
statusDrafting: '';
|
||||
statusLocked: '';
|
||||
statusPending: '';
|
||||
wordsCount: '';
|
||||
};
|
||||
conversation: {
|
||||
addMore: 'More';
|
||||
agentName: 'Life Echo';
|
||||
cancelRecording: 'Cancel recording';
|
||||
chatTitle: 'Conversation';
|
||||
connectionConnected: 'Connected';
|
||||
connectionConnecting: 'Connecting...';
|
||||
connectionDisconnected: 'Disconnected';
|
||||
emptyGreetingSubtitle: 'Chat with Echo and record your stories.';
|
||||
greetingTitle: 'Say Hello';
|
||||
inputPlaceholder: 'Type a message...';
|
||||
inputPlaceholderVoice: 'Type here or hold the mic to speak...';
|
||||
me: 'Me';
|
||||
read: 'Read';
|
||||
recentChats: 'Recent Chats';
|
||||
recordingPermissionDenied: 'Microphone permission is required to record';
|
||||
send: 'Send';
|
||||
startNewSubtitle: 'Capture a new memory or share your thoughts with Echo.';
|
||||
switchToText: 'Switch to text input';
|
||||
switchToVoice: 'Switch to voice input';
|
||||
tapToEndRecording: 'Tap to end';
|
||||
tapToStartRecording: 'Tap to start recording';
|
||||
unread: 'Unread';
|
||||
viewAll: 'View All';
|
||||
};
|
||||
explore: {};
|
||||
home: {};
|
||||
memoir: {
|
||||
chapterLabel: 'Chapter {{index}}';
|
||||
chapterReading: {
|
||||
back: 'Back';
|
||||
backgroundColor: 'Background';
|
||||
bgPureWhite: 'White';
|
||||
bgSepia: 'Sepia';
|
||||
chapterNotFound: 'Chapter not found';
|
||||
close: 'Close';
|
||||
fontSans: 'Sans';
|
||||
fontSerif: 'Serif';
|
||||
fontSize: 'Font Size';
|
||||
fontSizeDefault: 'Medium';
|
||||
fontSizeLarge: 'Large';
|
||||
fontSizeSmall: 'Small';
|
||||
readingSettings: 'Reading Settings';
|
||||
settings: 'Settings';
|
||||
typography: 'Typography';
|
||||
};
|
||||
continueWriting: 'Continue Writing';
|
||||
emptySubtitle: 'Chat with Echo to record your stories';
|
||||
emptyTitle: 'No memoir yet';
|
||||
pageTitle: 'Memoir';
|
||||
readMemory: 'Read Memory';
|
||||
startChapter: 'Start Writing';
|
||||
statusDrafting: 'Drafting';
|
||||
statusLocked: 'Locked';
|
||||
statusPending: 'Pending';
|
||||
wordsCount: '{{count}} words';
|
||||
};
|
||||
profile: {
|
||||
about: {
|
||||
aboutUs: 'About Us';
|
||||
title: 'About';
|
||||
};
|
||||
appExperience: {
|
||||
language: 'Language';
|
||||
languageDesc: 'App display language';
|
||||
largeText: 'Large Text';
|
||||
largeTextDesc: 'Make reading easier';
|
||||
nightMode: 'Night Mode';
|
||||
nightModeDesc: 'Use dark theme';
|
||||
theme: 'Theme';
|
||||
themeDesc: 'App color theme';
|
||||
title: 'App Experience';
|
||||
};
|
||||
dataPrivacy: {
|
||||
deleteAll: 'Delete All Data';
|
||||
deleteUnderDevelopment: 'Delete data feature is under development.';
|
||||
exportAll: 'Export All Data';
|
||||
exportUnderDevelopment: 'Export feature is under development.';
|
||||
title: 'Data & Privacy';
|
||||
};
|
||||
editAvatar: 'Edit Profile Picture';
|
||||
helpSupport: {
|
||||
faq: 'FAQ';
|
||||
feedback: 'Feedback & Support';
|
||||
feedbackPageTitle: 'Share your thoughts';
|
||||
title: 'Help & Support';
|
||||
};
|
||||
signOut: 'Sign Out';
|
||||
signingOut: 'Signing out...';
|
||||
userNamePlaceholder: 'User';
|
||||
userTier: '{{tier}}';
|
||||
};
|
||||
}
|
||||
|
||||
export default Resources;
|
||||
83
app-expo/src/i18n/index.ts
Normal file
83
app-expo/src/i18n/index.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { getLocales } from 'expo-localization';
|
||||
import { createInstance } from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import { AppState, type AppStateStatus } from 'react-native';
|
||||
|
||||
import {
|
||||
getAppLanguageOverride,
|
||||
setLanguageResolver,
|
||||
} from './language-resolver';
|
||||
import {
|
||||
defaultNS,
|
||||
fallbackLanguage,
|
||||
namespaces,
|
||||
resources,
|
||||
supportedLanguages,
|
||||
type AppLanguage,
|
||||
} from './resources';
|
||||
|
||||
export { setLanguageResolver };
|
||||
|
||||
function resolveLanguage(languageTag?: string | null): AppLanguage {
|
||||
if (!languageTag) {
|
||||
return fallbackLanguage;
|
||||
}
|
||||
|
||||
return languageTag.toLowerCase().startsWith('zh') ? 'zh' : 'en';
|
||||
}
|
||||
|
||||
export function getDeviceLanguage(): AppLanguage {
|
||||
const locale = getLocales()[0];
|
||||
return resolveLanguage(locale?.languageCode ?? locale?.languageTag);
|
||||
}
|
||||
|
||||
const i18n = createInstance();
|
||||
|
||||
if (!i18n.isInitialized) {
|
||||
void i18n.use(initReactI18next).init({
|
||||
resources,
|
||||
ns: [...namespaces],
|
||||
defaultNS,
|
||||
fallbackNS: defaultNS,
|
||||
lng: getDeviceLanguage(),
|
||||
fallbackLng: fallbackLanguage,
|
||||
supportedLngs: [...supportedLanguages],
|
||||
nonExplicitSupportedLngs: true,
|
||||
initImmediate: false,
|
||||
returnNull: false,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
react: {
|
||||
useSuspense: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs i18n language: uses app override if set, otherwise device language.
|
||||
*/
|
||||
export async function syncLanguageWithDevice() {
|
||||
const appOverride = await getAppLanguageOverride();
|
||||
const nextLanguage = appOverride ?? getDeviceLanguage();
|
||||
|
||||
if (i18n.resolvedLanguage !== nextLanguage) {
|
||||
await i18n.changeLanguage(nextLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
type Removable = {
|
||||
remove: () => void;
|
||||
};
|
||||
|
||||
export function startLocaleSync(): Removable {
|
||||
void syncLanguageWithDevice();
|
||||
|
||||
return AppState.addEventListener('change', (state: AppStateStatus) => {
|
||||
if (state === 'active') {
|
||||
void syncLanguageWithDevice();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default i18n;
|
||||
22
app-expo/src/i18n/language-resolver.ts
Normal file
22
app-expo/src/i18n/language-resolver.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { AppLanguage } from './resources';
|
||||
|
||||
type LanguageResolver = () => Promise<AppLanguage | null>;
|
||||
|
||||
let resolver: LanguageResolver = () => Promise.resolve(null);
|
||||
|
||||
/**
|
||||
* Injects the app language getter. Called at app startup (e.g. from _layout).
|
||||
* Enables i18n to resolve user override without importing app-settings directly,
|
||||
* which keeps i18n testable (no expo-secure-store in test env).
|
||||
*/
|
||||
export function setLanguageResolver(getter: LanguageResolver): void {
|
||||
resolver = getter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user's app language override, or null if using device default.
|
||||
* Used by syncLanguageWithDevice.
|
||||
*/
|
||||
export function getAppLanguageOverride(): Promise<AppLanguage | null> {
|
||||
return resolver();
|
||||
}
|
||||
18
app-expo/src/i18n/locales/en/app.json
Normal file
18
app-expo/src/i18n/locales/en/app.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"languages": {
|
||||
"en": "English",
|
||||
"system": "System",
|
||||
"zh": "Chinese"
|
||||
},
|
||||
"name": "Life Echo",
|
||||
"tabs": {
|
||||
"conversations": "Chats",
|
||||
"explore": "Explore",
|
||||
"home": "Home",
|
||||
"memoir": "Memoir",
|
||||
"profile": "Profile"
|
||||
},
|
||||
"theme": {
|
||||
"default": "Default"
|
||||
}
|
||||
}
|
||||
20
app-expo/src/i18n/locales/en/auth.json
Normal file
20
app-expo/src/i18n/locales/en/auth.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"login": {
|
||||
"codeLabel": "Verification Code",
|
||||
"getCode": "Get Code",
|
||||
"getCodeCountdown": "Retry in {{seconds}}s",
|
||||
"networkError": "Network error. Please try again later.",
|
||||
"phoneLabel": "Phone Number",
|
||||
"phonePlaceholder": "Enter your phone number",
|
||||
"privacyPolicy": "Privacy Policy",
|
||||
"submit": "Login",
|
||||
"termsAnd": "and",
|
||||
"termsIntro": "I agree to the",
|
||||
"termsRequired": "Please agree to the User Agreement and Privacy Policy first",
|
||||
"termsRequiredConfirm": "OK",
|
||||
"termsRequiredTitle": "Agreement Required",
|
||||
"userAgreement": "User Agreement",
|
||||
"welcomeSubtitle": "Some lives grow richer the more you savor them.",
|
||||
"welcomeTitle": "Welcome back"
|
||||
}
|
||||
}
|
||||
22
app-expo/src/i18n/locales/en/common.json
Normal file
22
app-expo/src/i18n/locales/en/common.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"chapterLabel": "",
|
||||
"chapterReading": {
|
||||
"backgroundColor": "",
|
||||
"bgPureWhite": "",
|
||||
"bgSepia": "",
|
||||
"close": "",
|
||||
"fontSize": "",
|
||||
"readingSettings": "",
|
||||
"typography": ""
|
||||
},
|
||||
"continueWriting": "",
|
||||
"docs": "Docs",
|
||||
"emptySubtitle": "",
|
||||
"emptyTitle": "",
|
||||
"readMemory": "",
|
||||
"startChapter": "",
|
||||
"statusDrafting": "",
|
||||
"statusLocked": "",
|
||||
"statusPending": "",
|
||||
"wordsCount": ""
|
||||
}
|
||||
26
app-expo/src/i18n/locales/en/conversation.json
Normal file
26
app-expo/src/i18n/locales/en/conversation.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"addMore": "More",
|
||||
"agentName": "Life Echo",
|
||||
"cancelRecording": "Cancel recording",
|
||||
"chatTitle": "Conversation",
|
||||
"connectionConnected": "Connected",
|
||||
"connectionConnecting": "Connecting...",
|
||||
"connectionDisconnected": "Disconnected",
|
||||
"emptyGreetingSubtitle": "Chat with Echo and record your stories.",
|
||||
"greetingTitle": "Say Hello",
|
||||
"inputPlaceholder": "Type a message...",
|
||||
"inputPlaceholderVoice": "Type here or hold the mic to speak...",
|
||||
"me": "Me",
|
||||
"read": "Read",
|
||||
"recentChats": "Recent Chats",
|
||||
"recordingPermissionDenied": "Microphone permission is required to record",
|
||||
"send": "Send",
|
||||
"startNewSubtitle": "Capture a new memory or share your thoughts with Echo.",
|
||||
"switchToText": "Switch to text input",
|
||||
"switchToVoice": "Switch to voice input",
|
||||
"tapToEndRecording": "Tap to end",
|
||||
"tapToStartRecording": "Tap to start recording",
|
||||
"unread": "Unread",
|
||||
"viewAll": "View All",
|
||||
"voiceMessagePreview": "Voice message"
|
||||
}
|
||||
1
app-expo/src/i18n/locales/en/explore.json
Normal file
1
app-expo/src/i18n/locales/en/explore.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
1
app-expo/src/i18n/locales/en/home.json
Normal file
1
app-expo/src/i18n/locales/en/home.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
8
app-expo/src/i18n/locales/en/memoir.json
Normal file
8
app-expo/src/i18n/locales/en/memoir.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"chapterReading": {
|
||||
"back": "Back",
|
||||
"chapterNotFound": "Chapter not found",
|
||||
"settings": "Settings"
|
||||
},
|
||||
"pageTitle": "Memoir"
|
||||
}
|
||||
35
app-expo/src/i18n/locales/en/profile.json
Normal file
35
app-expo/src/i18n/locales/en/profile.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"about": {
|
||||
"aboutUs": "About Us",
|
||||
"title": "About"
|
||||
},
|
||||
"appExperience": {
|
||||
"language": "Language",
|
||||
"languageDesc": "App display language",
|
||||
"largeText": "Large Text",
|
||||
"largeTextDesc": "Make reading easier",
|
||||
"nightMode": "Night Mode",
|
||||
"nightModeDesc": "Use dark theme",
|
||||
"theme": "Theme",
|
||||
"themeDesc": "App color theme",
|
||||
"title": "App Experience"
|
||||
},
|
||||
"dataPrivacy": {
|
||||
"deleteAll": "Delete All Data",
|
||||
"deleteUnderDevelopment": "Delete data feature is under development.",
|
||||
"exportAll": "Export All Data",
|
||||
"exportUnderDevelopment": "Export feature is under development.",
|
||||
"title": "Data & Privacy"
|
||||
},
|
||||
"editAvatar": "Edit Profile Picture",
|
||||
"helpSupport": {
|
||||
"faq": "FAQ",
|
||||
"feedback": "Feedback & Support",
|
||||
"feedbackPageTitle": "Share your thoughts",
|
||||
"title": "Help & Support"
|
||||
},
|
||||
"signingOut": "Signing out...",
|
||||
"signOut": "Sign Out",
|
||||
"userNamePlaceholder": "User",
|
||||
"userTier": "{{tier}}"
|
||||
}
|
||||
18
app-expo/src/i18n/locales/zh/app.json
Normal file
18
app-expo/src/i18n/locales/zh/app.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"languages": {
|
||||
"en": "英文",
|
||||
"system": "跟随系统",
|
||||
"zh": "中文"
|
||||
},
|
||||
"name": "岁月时书",
|
||||
"tabs": {
|
||||
"conversations": "对话",
|
||||
"explore": "探索",
|
||||
"home": "首页",
|
||||
"memoir": "回忆录",
|
||||
"profile": "我的"
|
||||
},
|
||||
"theme": {
|
||||
"default": "默认"
|
||||
}
|
||||
}
|
||||
20
app-expo/src/i18n/locales/zh/auth.json
Normal file
20
app-expo/src/i18n/locales/zh/auth.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"login": {
|
||||
"codeLabel": "验证码",
|
||||
"getCode": "获取验证码",
|
||||
"getCodeCountdown": "{{seconds}}s 后重试",
|
||||
"networkError": "网络异常,请稍后重试",
|
||||
"phoneLabel": "手机号",
|
||||
"phonePlaceholder": "请输入手机号",
|
||||
"privacyPolicy": "《隐私政策》",
|
||||
"submit": "登录",
|
||||
"termsAnd": "和",
|
||||
"termsIntro": "我已阅读并同意",
|
||||
"termsRequired": "请先同意用户协议和隐私政策",
|
||||
"termsRequiredConfirm": "知道了",
|
||||
"termsRequiredTitle": "需要同意协议",
|
||||
"userAgreement": "《用户协议》",
|
||||
"welcomeSubtitle": "有些人生,越嚼越有味道。",
|
||||
"welcomeTitle": "欢迎回来"
|
||||
}
|
||||
}
|
||||
22
app-expo/src/i18n/locales/zh/common.json
Normal file
22
app-expo/src/i18n/locales/zh/common.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"chapterLabel": "chapterLabel",
|
||||
"chapterReading": {
|
||||
"backgroundColor": "chapterReading.backgroundColor",
|
||||
"bgPureWhite": "chapterReading.bgPureWhite",
|
||||
"bgSepia": "chapterReading.bgSepia",
|
||||
"close": "chapterReading.close",
|
||||
"fontSize": "chapterReading.fontSize",
|
||||
"readingSettings": "chapterReading.readingSettings",
|
||||
"typography": "chapterReading.typography"
|
||||
},
|
||||
"continueWriting": "continueWriting",
|
||||
"docs": "文档",
|
||||
"emptySubtitle": "emptySubtitle",
|
||||
"emptyTitle": "emptyTitle",
|
||||
"readMemory": "readMemory",
|
||||
"startChapter": "startChapter",
|
||||
"statusDrafting": "statusDrafting",
|
||||
"statusLocked": "statusLocked",
|
||||
"statusPending": "statusPending",
|
||||
"wordsCount": "wordsCount"
|
||||
}
|
||||
26
app-expo/src/i18n/locales/zh/conversation.json
Normal file
26
app-expo/src/i18n/locales/zh/conversation.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"addMore": "更多功能",
|
||||
"agentName": "岁月知己",
|
||||
"cancelRecording": "取消录音发送",
|
||||
"chatTitle": "对话",
|
||||
"connectionConnected": "已连接",
|
||||
"connectionConnecting": "连接中...",
|
||||
"connectionDisconnected": "未连接",
|
||||
"emptyGreetingSubtitle": "和 Echo 聊聊,记录你的故事。",
|
||||
"greetingTitle": "打个招呼",
|
||||
"inputPlaceholder": "输入消息...",
|
||||
"inputPlaceholderVoice": "点击这里输入,或者按住左边说话...",
|
||||
"me": "我",
|
||||
"read": "已读",
|
||||
"recentChats": "最近对话",
|
||||
"recordingPermissionDenied": "需要麦克风权限才能录音",
|
||||
"send": "发送",
|
||||
"startNewSubtitle": "记录新回忆,或与 Echo 分享你的想法。",
|
||||
"switchToText": "切换到文字输入",
|
||||
"switchToVoice": "切换到语音输入",
|
||||
"tapToEndRecording": "点击结束",
|
||||
"tapToStartRecording": "点击开始录音",
|
||||
"unread": "未读",
|
||||
"viewAll": "查看全部",
|
||||
"voiceMessagePreview": "语音消息"
|
||||
}
|
||||
1
app-expo/src/i18n/locales/zh/explore.json
Normal file
1
app-expo/src/i18n/locales/zh/explore.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
1
app-expo/src/i18n/locales/zh/home.json
Normal file
1
app-expo/src/i18n/locales/zh/home.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
8
app-expo/src/i18n/locales/zh/memoir.json
Normal file
8
app-expo/src/i18n/locales/zh/memoir.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"chapterReading": {
|
||||
"back": "返回",
|
||||
"chapterNotFound": "章节未找到",
|
||||
"settings": "设置"
|
||||
},
|
||||
"pageTitle": "回忆录"
|
||||
}
|
||||
35
app-expo/src/i18n/locales/zh/profile.json
Normal file
35
app-expo/src/i18n/locales/zh/profile.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"about": {
|
||||
"aboutUs": "关于我们",
|
||||
"title": "关于"
|
||||
},
|
||||
"appExperience": {
|
||||
"language": "语言",
|
||||
"languageDesc": "应用显示语言",
|
||||
"largeText": "大字模式",
|
||||
"largeTextDesc": "让阅读更轻松",
|
||||
"nightMode": "夜间模式",
|
||||
"nightModeDesc": "使用深色主题",
|
||||
"theme": "主题",
|
||||
"themeDesc": "应用配色主题",
|
||||
"title": "应用体验"
|
||||
},
|
||||
"dataPrivacy": {
|
||||
"deleteAll": "删除所有数据",
|
||||
"deleteUnderDevelopment": "删除数据功能开发中,敬请期待。",
|
||||
"exportAll": "导出所有数据",
|
||||
"exportUnderDevelopment": "导出功能开发中,敬请期待。",
|
||||
"title": "数据与隐私"
|
||||
},
|
||||
"editAvatar": "编辑头像",
|
||||
"helpSupport": {
|
||||
"faq": "常见问题",
|
||||
"feedback": "反馈与客服",
|
||||
"feedbackPageTitle": "说说你的想法",
|
||||
"title": "帮助与支持"
|
||||
},
|
||||
"signingOut": "退出中...",
|
||||
"signOut": "退出登录",
|
||||
"userNamePlaceholder": "用户",
|
||||
"userTier": "{{tier}}"
|
||||
}
|
||||
58
app-expo/src/i18n/resources/index.ts
Normal file
58
app-expo/src/i18n/resources/index.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import appEn from '../locales/en/app.json';
|
||||
import authEn from '../locales/en/auth.json';
|
||||
import commonEn from '../locales/en/common.json';
|
||||
import conversationEn from '../locales/en/conversation.json';
|
||||
import exploreEn from '../locales/en/explore.json';
|
||||
import homeEn from '../locales/en/home.json';
|
||||
import memoirEn from '../locales/en/memoir.json';
|
||||
import profileEn from '../locales/en/profile.json';
|
||||
import appZh from '../locales/zh/app.json';
|
||||
import authZh from '../locales/zh/auth.json';
|
||||
import commonZh from '../locales/zh/common.json';
|
||||
import conversationZh from '../locales/zh/conversation.json';
|
||||
import exploreZh from '../locales/zh/explore.json';
|
||||
import homeZh from '../locales/zh/home.json';
|
||||
import memoirZh from '../locales/zh/memoir.json';
|
||||
import profileZh from '../locales/zh/profile.json';
|
||||
|
||||
export const supportedLanguages = ['zh', 'en'] as const;
|
||||
|
||||
export type AppLanguage = (typeof supportedLanguages)[number];
|
||||
|
||||
export const fallbackLanguage: AppLanguage = 'zh';
|
||||
|
||||
export const namespaces = [
|
||||
'app',
|
||||
'auth',
|
||||
'common',
|
||||
'conversation',
|
||||
'home',
|
||||
'explore',
|
||||
'memoir',
|
||||
'profile',
|
||||
] as const;
|
||||
|
||||
export const defaultNS = 'common' as const;
|
||||
|
||||
export const resources = {
|
||||
zh: {
|
||||
app: appZh,
|
||||
auth: authZh,
|
||||
common: commonZh,
|
||||
conversation: conversationZh,
|
||||
home: homeZh,
|
||||
explore: exploreZh,
|
||||
memoir: memoirZh,
|
||||
profile: profileZh,
|
||||
},
|
||||
en: {
|
||||
app: appEn,
|
||||
auth: authEn,
|
||||
common: commonEn,
|
||||
conversation: conversationEn,
|
||||
home: homeEn,
|
||||
explore: exploreEn,
|
||||
memoir: memoirEn,
|
||||
profile: profileEn,
|
||||
},
|
||||
} as const;
|
||||
Reference in New Issue
Block a user