@umituz/react-native-localization 2.7.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +21 -10
- package/scripts/prepublish.js +29 -16
- package/src/domain/repositories/ILocalizationRepository.ts +2 -2
- package/src/index.ts +5 -1
- package/src/infrastructure/components/LanguageSwitcher.tsx +90 -37
- package/src/infrastructure/components/LocalizationProvider.tsx +115 -7
- package/src/infrastructure/components/__tests__/LanguageSwitcher.test.tsx +91 -0
- package/src/infrastructure/components/useLanguageNavigation.ts +4 -4
- package/src/infrastructure/config/TranslationCache.ts +27 -0
- package/src/infrastructure/config/TranslationLoader.ts +4 -8
- package/src/infrastructure/config/__tests__/TranslationCache.test.ts +44 -0
- package/src/infrastructure/config/__tests__/languagesData.test.ts +49 -0
- package/src/infrastructure/config/languages.ts +1 -1
- package/src/infrastructure/config/languagesData.ts +91 -61
- package/src/infrastructure/hooks/__tests__/useTranslation.test.ts +52 -0
- package/src/infrastructure/hooks/useLocalization.ts +58 -0
- package/src/infrastructure/hooks/useTranslation.ts +84 -29
- package/src/infrastructure/storage/LanguageInitializer.ts +7 -5
- package/src/infrastructure/storage/LanguageSwitcher.ts +3 -3
- package/src/infrastructure/storage/LocalizationStore.ts +103 -94
- package/src/infrastructure/storage/types/LocalizationState.ts +31 -0
- package/src/presentation/components/LanguageItem.tsx +109 -0
- package/src/presentation/components/SearchInput.tsx +90 -0
- package/src/presentation/components/__tests__/LanguageItem.test.tsx +106 -0
- package/src/presentation/components/__tests__/SearchInput.test.tsx +95 -0
- package/src/presentation/screens/LanguageSelectionScreen.tsx +148 -0
- package/src/presentation/screens/__tests__/LanguageSelectionScreen.test.tsx +166 -0
- package/src/scripts/prepublish.ts +48 -0
- package/src/infrastructure/locales/en-US/alerts.json +0 -107
- package/src/infrastructure/locales/en-US/auth.json +0 -34
- package/src/infrastructure/locales/en-US/branding.json +0 -8
- package/src/infrastructure/locales/en-US/clipboard.json +0 -9
- package/src/infrastructure/locales/en-US/common.json +0 -57
- package/src/infrastructure/locales/en-US/datetime.json +0 -138
- package/src/infrastructure/locales/en-US/device.json +0 -14
- package/src/infrastructure/locales/en-US/editor.json +0 -64
- package/src/infrastructure/locales/en-US/errors.json +0 -41
- package/src/infrastructure/locales/en-US/general.json +0 -57
- package/src/infrastructure/locales/en-US/goals.json +0 -5
- package/src/infrastructure/locales/en-US/haptics.json +0 -6
- package/src/infrastructure/locales/en-US/home.json +0 -62
- package/src/infrastructure/locales/en-US/index.ts +0 -54
- package/src/infrastructure/locales/en-US/navigation.json +0 -6
- package/src/infrastructure/locales/en-US/onboarding.json +0 -26
- package/src/infrastructure/locales/en-US/projects.json +0 -34
- package/src/infrastructure/locales/en-US/settings.json +0 -45
- package/src/infrastructure/locales/en-US/sharing.json +0 -8
- package/src/infrastructure/locales/en-US/templates.json +0 -28
- package/src/infrastructure/scripts/createLocaleLoaders.js +0 -177
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Selection Screen
|
|
3
|
+
*
|
|
4
|
+
* Language picker with search functionality
|
|
5
|
+
*
|
|
6
|
+
* Generic language selector that can be customized by consuming applications
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React, { useState, useMemo } from 'react';
|
|
10
|
+
import {
|
|
11
|
+
View,
|
|
12
|
+
StyleSheet,
|
|
13
|
+
FlatList,
|
|
14
|
+
} from 'react-native';
|
|
15
|
+
// @ts-ignore - Optional peer dependency
|
|
16
|
+
import { useNavigation } from '@react-navigation/native';
|
|
17
|
+
import { useLocalization, searchLanguages, Language } from '../../index';
|
|
18
|
+
import { LanguageItem } from '../components/LanguageItem';
|
|
19
|
+
import { SearchInput } from '../components/SearchInput';
|
|
20
|
+
|
|
21
|
+
interface LanguageSelectionScreenProps {
|
|
22
|
+
/**
|
|
23
|
+
* Custom component for rendering language items
|
|
24
|
+
*/
|
|
25
|
+
renderLanguageItem?: (item: Language, isSelected: boolean, onSelect: (code: string) => void) => React.ReactNode;
|
|
26
|
+
/**
|
|
27
|
+
* Custom component for search input
|
|
28
|
+
*/
|
|
29
|
+
renderSearchInput?: (value: string, onChange: (value: string) => void, placeholder: string) => React.ReactNode;
|
|
30
|
+
/**
|
|
31
|
+
* Custom component for container
|
|
32
|
+
*/
|
|
33
|
+
containerComponent?: React.ComponentType<{ children: React.ReactNode }>;
|
|
34
|
+
/**
|
|
35
|
+
* Custom styles
|
|
36
|
+
*/
|
|
37
|
+
styles?: {
|
|
38
|
+
container?: any;
|
|
39
|
+
searchContainer?: any;
|
|
40
|
+
languageItem?: any;
|
|
41
|
+
languageContent?: any;
|
|
42
|
+
languageText?: any;
|
|
43
|
+
flag?: any;
|
|
44
|
+
nativeName?: any;
|
|
45
|
+
searchInput?: any;
|
|
46
|
+
searchIcon?: any;
|
|
47
|
+
clearButton?: any;
|
|
48
|
+
listContent?: any;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Search placeholder text
|
|
52
|
+
*/
|
|
53
|
+
searchPlaceholder: string;
|
|
54
|
+
/**
|
|
55
|
+
* Test ID for testing
|
|
56
|
+
*/
|
|
57
|
+
testID?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Language Selection Screen Component
|
|
62
|
+
* Generic language selector that can be customized by consuming applications
|
|
63
|
+
*/
|
|
64
|
+
export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = ({
|
|
65
|
+
renderLanguageItem,
|
|
66
|
+
renderSearchInput,
|
|
67
|
+
containerComponent: Container,
|
|
68
|
+
styles: customStyles,
|
|
69
|
+
searchPlaceholder,
|
|
70
|
+
testID = 'language-selection-screen',
|
|
71
|
+
}) => {
|
|
72
|
+
const navigation = useNavigation();
|
|
73
|
+
const { t, currentLanguage, setLanguage } = useLocalization();
|
|
74
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
75
|
+
const [selectedCode, setSelectedCode] = useState(currentLanguage);
|
|
76
|
+
|
|
77
|
+
const filteredLanguages = useMemo(() => {
|
|
78
|
+
return searchLanguages(searchQuery);
|
|
79
|
+
}, [searchQuery]);
|
|
80
|
+
|
|
81
|
+
const handleLanguageSelect = async (code: string) => {
|
|
82
|
+
setSelectedCode(code);
|
|
83
|
+
await setLanguage(code);
|
|
84
|
+
navigation.goBack();
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const renderItem = ({ item }: { item: Language }) => {
|
|
88
|
+
const isSelected = selectedCode === item.code;
|
|
89
|
+
|
|
90
|
+
if (renderLanguageItem) {
|
|
91
|
+
const customItem = renderLanguageItem(item, isSelected, handleLanguageSelect);
|
|
92
|
+
return <>{customItem}</>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<LanguageItem
|
|
97
|
+
item={item}
|
|
98
|
+
isSelected={isSelected}
|
|
99
|
+
onSelect={handleLanguageSelect}
|
|
100
|
+
customStyles={customStyles}
|
|
101
|
+
/>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const renderSearchInputComponent = () => {
|
|
106
|
+
if (renderSearchInput) {
|
|
107
|
+
return renderSearchInput(searchQuery, setSearchQuery, searchPlaceholder);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<SearchInput
|
|
112
|
+
value={searchQuery}
|
|
113
|
+
onChange={setSearchQuery}
|
|
114
|
+
placeholder={searchPlaceholder}
|
|
115
|
+
customStyles={customStyles}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const content = (
|
|
121
|
+
<View style={[styles.container, customStyles?.container]} testID={testID}>
|
|
122
|
+
{renderSearchInputComponent()}
|
|
123
|
+
<FlatList
|
|
124
|
+
data={filteredLanguages}
|
|
125
|
+
renderItem={renderItem}
|
|
126
|
+
keyExtractor={item => item.code}
|
|
127
|
+
contentContainerStyle={[styles.listContent, customStyles?.listContent]}
|
|
128
|
+
showsVerticalScrollIndicator={false}
|
|
129
|
+
keyboardShouldPersistTaps="handled"
|
|
130
|
+
/>
|
|
131
|
+
</View>
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
return Container ? <Container>{content}</Container> : content;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const styles = StyleSheet.create({
|
|
138
|
+
container: {
|
|
139
|
+
flex: 1,
|
|
140
|
+
backgroundColor: '#fff',
|
|
141
|
+
},
|
|
142
|
+
listContent: {
|
|
143
|
+
paddingHorizontal: 20,
|
|
144
|
+
paddingBottom: 32,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
export default LanguageSelectionScreen;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Selection Screen Tests
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { render, fireEvent } from '@testing-library/react-native';
|
|
7
|
+
import { LanguageSelectionScreen } from '../LanguageSelectionScreen';
|
|
8
|
+
import { useLocalization } from '../../infrastructure/hooks/useLocalization';
|
|
9
|
+
import { searchLanguages } from '../../infrastructure/config/languagesData';
|
|
10
|
+
|
|
11
|
+
// Mock dependencies
|
|
12
|
+
jest.mock('../../infrastructure/hooks/useLocalization');
|
|
13
|
+
jest.mock('../../infrastructure/config/languagesData');
|
|
14
|
+
jest.mock('@react-navigation/native', () => ({
|
|
15
|
+
useNavigation: () => ({
|
|
16
|
+
goBack: jest.fn(),
|
|
17
|
+
}),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
const mockUseLocalization = useLocalization as jest.MockedFunction<typeof useLocalization>;
|
|
21
|
+
const mockSearchLanguages = searchLanguages as jest.MockedFunction<typeof searchLanguages>;
|
|
22
|
+
|
|
23
|
+
const mockLanguage = {
|
|
24
|
+
code: 'en-US',
|
|
25
|
+
name: 'English',
|
|
26
|
+
nativeName: 'English',
|
|
27
|
+
flag: '🇺🇸',
|
|
28
|
+
isRTL: false,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe('LanguageSelectionScreen', () => {
|
|
32
|
+
const mockSetLanguage = jest.fn();
|
|
33
|
+
const mockGoBack = jest.fn();
|
|
34
|
+
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
jest.clearAllMocks();
|
|
37
|
+
|
|
38
|
+
mockUseLocalization.mockReturnValue({
|
|
39
|
+
currentLanguage: 'en-US',
|
|
40
|
+
setLanguage: mockSetLanguage,
|
|
41
|
+
t: jest.fn(),
|
|
42
|
+
} as any);
|
|
43
|
+
|
|
44
|
+
mockSearchLanguages.mockReturnValue([mockLanguage]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should render search input and language list', () => {
|
|
48
|
+
const { getByPlaceholderText, getByText } = render(
|
|
49
|
+
<LanguageSelectionScreen
|
|
50
|
+
searchPlaceholder="Search languages..."
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(getByPlaceholderText('Search languages...')).toBeTruthy();
|
|
55
|
+
expect(getByText('English')).toBeTruthy();
|
|
56
|
+
expect(getByText('🇺🇸')).toBeTruthy();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should filter languages when searching', () => {
|
|
60
|
+
const { getByPlaceholderText } = render(
|
|
61
|
+
<LanguageSelectionScreen
|
|
62
|
+
searchPlaceholder="Search languages..."
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
fireEvent.changeText(getByPlaceholderText('Search languages...'), 'test');
|
|
67
|
+
expect(mockSearchLanguages).toHaveBeenCalledWith('test');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should select language when item is pressed', async () => {
|
|
71
|
+
const { getByText } = render(
|
|
72
|
+
<LanguageSelectionScreen
|
|
73
|
+
searchPlaceholder="Search languages..."
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
fireEvent.press(getByText('English'));
|
|
78
|
+
expect(mockSetLanguage).toHaveBeenCalledWith('en-US');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should show check icon for selected language', () => {
|
|
82
|
+
const { getByText } = render(
|
|
83
|
+
<LanguageSelectionScreen
|
|
84
|
+
searchPlaceholder="Search languages..."
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(getByText('✓')).toBeTruthy();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should use custom render function when provided', () => {
|
|
92
|
+
const customRender = jest.fn().mockReturnValue(<div>Custom Item</div>);
|
|
93
|
+
|
|
94
|
+
render(
|
|
95
|
+
<LanguageSelectionScreen
|
|
96
|
+
searchPlaceholder="Search languages..."
|
|
97
|
+
renderLanguageItem={customRender}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
expect(customRender).toHaveBeenCalledWith(
|
|
102
|
+
mockLanguage,
|
|
103
|
+
true,
|
|
104
|
+
expect.any(Function)
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should use custom search input when provided', () => {
|
|
109
|
+
const customSearchInput = jest.fn().mockReturnValue(<div>Custom Search</div>);
|
|
110
|
+
|
|
111
|
+
render(
|
|
112
|
+
<LanguageSelectionScreen
|
|
113
|
+
searchPlaceholder="Search languages..."
|
|
114
|
+
renderSearchInput={customSearchInput}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
expect(customSearchInput).toHaveBeenCalledWith(
|
|
119
|
+
'',
|
|
120
|
+
expect.any(Function),
|
|
121
|
+
'Search languages...'
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should use custom container when provided', () => {
|
|
126
|
+
const CustomContainer = ({ children }: { children: React.ReactNode }) => (
|
|
127
|
+
<div testID="custom-container">{children}</div>
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const { getByTestId } = render(
|
|
131
|
+
<LanguageSelectionScreen
|
|
132
|
+
searchPlaceholder="Search languages..."
|
|
133
|
+
containerComponent={CustomContainer}
|
|
134
|
+
/>
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
expect(getByTestId('custom-container')).toBeTruthy();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should apply custom styles', () => {
|
|
141
|
+
const customStyles = {
|
|
142
|
+
container: { backgroundColor: 'red' },
|
|
143
|
+
languageItem: { borderColor: 'blue' },
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const { getByTestId } = render(
|
|
147
|
+
<LanguageSelectionScreen
|
|
148
|
+
searchPlaceholder="Search languages..."
|
|
149
|
+
styles={customStyles}
|
|
150
|
+
/>
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
expect(getByTestId('language-selection-screen')).toHaveStyle({ backgroundColor: 'red' });
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should use custom test ID when provided', () => {
|
|
157
|
+
const { getByTestId } = render(
|
|
158
|
+
<LanguageSelectionScreen
|
|
159
|
+
searchPlaceholder="Search languages..."
|
|
160
|
+
testID="custom-test-id"
|
|
161
|
+
/>
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
expect(getByTestId('custom-test-id')).toBeTruthy();
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pre-Publish Script - Generic Package Version
|
|
6
|
+
*
|
|
7
|
+
* Basic checks before publishing for generic localization package
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
17
|
+
const SRC_DIR = path.join(PACKAGE_ROOT, 'src');
|
|
18
|
+
|
|
19
|
+
console.log('🔍 Pre-publish checks...\n');
|
|
20
|
+
|
|
21
|
+
// Check if src directory exists
|
|
22
|
+
if (!fs.existsSync(SRC_DIR)) {
|
|
23
|
+
console.error('❌ src directory not found!');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check if main files exist
|
|
28
|
+
const mainFiles = [
|
|
29
|
+
'src/index.ts',
|
|
30
|
+
'src/infrastructure/config/i18n.ts',
|
|
31
|
+
'src/infrastructure/storage/LocalizationStore.ts',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
let allFilesExist = true;
|
|
35
|
+
for (const file of mainFiles) {
|
|
36
|
+
const filePath = path.join(PACKAGE_ROOT, file);
|
|
37
|
+
if (!fs.existsSync(filePath)) {
|
|
38
|
+
console.error(`❌ Required file not found: ${file}`);
|
|
39
|
+
allFilesExist = false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!allFilesExist) {
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log('✅ All required files found');
|
|
48
|
+
console.log('✅ Pre-publish checks passed!\n');
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"error": {
|
|
3
|
-
"title": "Error",
|
|
4
|
-
"generic": "An error occurred",
|
|
5
|
-
"failed_to_select_video": "Failed to select video",
|
|
6
|
-
"failed_to_select_images": "Failed to select images",
|
|
7
|
-
"failed_to_select_audio": "Failed to select audio file",
|
|
8
|
-
"failed_to_generate_video": "Failed to generate video",
|
|
9
|
-
"failed_to_transform_video": "Failed to transform video",
|
|
10
|
-
"failed_to_generate_script": "Failed to generate script",
|
|
11
|
-
"failed_to_export": "Export failed",
|
|
12
|
-
"failed_to_pick_image": "Failed to pick image. Please try again.",
|
|
13
|
-
"failed_to_take_photo": "Failed to take photo. Please try again.",
|
|
14
|
-
"project_not_found": "Project not found",
|
|
15
|
-
"cannot_delete_last_scene": "Cannot delete the last scene",
|
|
16
|
-
"configuration_error": "Firebase is not configured. Please check your environment settings.",
|
|
17
|
-
"sign_in_failed": "Failed to sign in. Please try again.",
|
|
18
|
-
"sign_up_failed": "Failed to create account. Please try again.",
|
|
19
|
-
"sign_in_google_failed": "Failed to sign in with Google.",
|
|
20
|
-
"sign_up_google_failed": "Failed to sign up with Google."
|
|
21
|
-
},
|
|
22
|
-
"success": {
|
|
23
|
-
"title": "Success",
|
|
24
|
-
"project_saved": "Project saved successfully!",
|
|
25
|
-
"text_layer_added": "Text layer added!",
|
|
26
|
-
"text_layer_updated": "Text layer updated!",
|
|
27
|
-
"layer_deleted": "Layer deleted",
|
|
28
|
-
"layer_duplicated": "Layer duplicated!",
|
|
29
|
-
"scene_added": "New scene added!",
|
|
30
|
-
"scene_duplicated": "Scene duplicated!",
|
|
31
|
-
"scene_deleted": "Scene deleted",
|
|
32
|
-
"image_layer_added": "Image layer added!",
|
|
33
|
-
"image_layer_updated": "Image layer updated!",
|
|
34
|
-
"shape_layer_added": "Shape layer added!",
|
|
35
|
-
"audio_added": "Audio added to scene!",
|
|
36
|
-
"audio_removed": "Audio removed from scene",
|
|
37
|
-
"animation_applied": "Animation applied to layer!",
|
|
38
|
-
"animation_removed": "Animation removed from layer",
|
|
39
|
-
"custom_audio_selected": "Custom audio selected!",
|
|
40
|
-
"video_created": "Video Created! 🎬",
|
|
41
|
-
"video_generated": "Video Generated! 🎉",
|
|
42
|
-
"script_copied": "Copied!",
|
|
43
|
-
"password_reset_sent": "Password reset link sent to your email.",
|
|
44
|
-
"account_created": "Your account has been created successfully.",
|
|
45
|
-
"project_deleted": "{{title}} deleted successfully",
|
|
46
|
-
"project_duplicated": "Project duplicated: {{title}}"
|
|
47
|
-
},
|
|
48
|
-
"validation": {
|
|
49
|
-
"missing_prompt": "Missing Prompt",
|
|
50
|
-
"missing_prompt_message": "Please enter a description for your video",
|
|
51
|
-
"missing_topic": "Missing Topic",
|
|
52
|
-
"missing_topic_message": "Please enter a topic for your video",
|
|
53
|
-
"missing_email": "Enter Email",
|
|
54
|
-
"missing_email_message": "Please enter your email address first.",
|
|
55
|
-
"enter_name": "Please enter your name",
|
|
56
|
-
"enter_email": "Please enter your email",
|
|
57
|
-
"enter_valid_email": "Please enter a valid email address",
|
|
58
|
-
"enter_password": "Please enter a password",
|
|
59
|
-
"enter_email_password": "Please enter email and password",
|
|
60
|
-
"password_min_length": "Password must be at least 6 characters",
|
|
61
|
-
"passwords_not_match": "Passwords do not match",
|
|
62
|
-
"no_video_selected": "No Video",
|
|
63
|
-
"no_video_selected_message": "Please select a video first",
|
|
64
|
-
"no_image_selected": "No Image",
|
|
65
|
-
"no_image_selected_message": "Please select an image first.",
|
|
66
|
-
"no_audio_selected": "Please select an audio file"
|
|
67
|
-
},
|
|
68
|
-
"video": {
|
|
69
|
-
"generation_failed": "Generation Failed",
|
|
70
|
-
"generation_failed_message": "Unable to generate video",
|
|
71
|
-
"transformation_failed": "Transformation Failed",
|
|
72
|
-
"transformation_failed_message": "Unable to transform video",
|
|
73
|
-
"video_ready": "Your AI-generated video is ready!",
|
|
74
|
-
"video_created_message": "Created {{count}} animated scenes with {{style}} effect"
|
|
75
|
-
},
|
|
76
|
-
"script": {
|
|
77
|
-
"generation_failed": "Generation Failed",
|
|
78
|
-
"generation_failed_message": "Unable to generate script"
|
|
79
|
-
},
|
|
80
|
-
"export": {
|
|
81
|
-
"title": "Export Complete",
|
|
82
|
-
"message": "Your video has been exported successfully!\n\nLocation: {{uri}}",
|
|
83
|
-
"failed_title": "Export Failed",
|
|
84
|
-
"failed_message": "An error occurred during export"
|
|
85
|
-
},
|
|
86
|
-
"delete": {
|
|
87
|
-
"layer_title": "Delete Layer",
|
|
88
|
-
"layer_message": "Are you sure you want to delete this layer?",
|
|
89
|
-
"scene_title": "Delete Scene",
|
|
90
|
-
"scene_message": "Are you sure you want to delete this scene?"
|
|
91
|
-
},
|
|
92
|
-
"actions": {
|
|
93
|
-
"undo": "Undo",
|
|
94
|
-
"undo_message": "Action undone",
|
|
95
|
-
"redo": "Redo",
|
|
96
|
-
"redo_message": "Action done",
|
|
97
|
-
"coming_soon": "Coming soon!",
|
|
98
|
-
"export_coming_soon": "Export feature coming soon!",
|
|
99
|
-
"share_coming_soon": "Share feature coming soon!",
|
|
100
|
-
"effects_coming_soon": "Effects feature coming soon!"
|
|
101
|
-
},
|
|
102
|
-
"premium": {
|
|
103
|
-
"upgrade_successful": "🎉 Upgrade Successful!",
|
|
104
|
-
"upgrade_message": "Welcome to Premium! You now have unlimited access to all features.",
|
|
105
|
-
"start_creating": "Start Creating"
|
|
106
|
-
}
|
|
107
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"title": "Welcome",
|
|
3
|
-
"subtitle": "Sign in to your account or continue as guest",
|
|
4
|
-
"welcomeBack": "Welcome Back",
|
|
5
|
-
"loginSubtitle": "Sign in to sync your data across devices",
|
|
6
|
-
"email": "Email",
|
|
7
|
-
"emailPlaceholder": "Enter your email",
|
|
8
|
-
"password": "Password",
|
|
9
|
-
"passwordPlaceholder": "Enter your password",
|
|
10
|
-
"signIn": "Sign In",
|
|
11
|
-
"createAccount": "Create Account",
|
|
12
|
-
"continueAsGuest": "Continue as Guest",
|
|
13
|
-
"dontHaveAccount": "Don't have an account?",
|
|
14
|
-
"register": "Register",
|
|
15
|
-
"displayName": "Display Name",
|
|
16
|
-
"displayNamePlaceholder": "Enter your name",
|
|
17
|
-
"confirmPassword": "Confirm Password",
|
|
18
|
-
"confirmPasswordPlaceholder": "Re-enter your password",
|
|
19
|
-
"backToLogin": "Back to Login",
|
|
20
|
-
"registerSubtitle": "Create an account to sync your data",
|
|
21
|
-
"fillAllFields": "Please fill in all fields",
|
|
22
|
-
"passwordsDoNotMatch": "Passwords do not match",
|
|
23
|
-
"passwordTooShort": "Password must be at least 6 characters",
|
|
24
|
-
"loginFailed": "Login failed. Please check your credentials.",
|
|
25
|
-
"registrationFailed": "Registration failed. Please try again.",
|
|
26
|
-
"logout": "Logout",
|
|
27
|
-
"signedInAs": "Signed in as",
|
|
28
|
-
"guestMode": "Guest Mode",
|
|
29
|
-
"guestModeDescription": "Your data is stored locally on this device",
|
|
30
|
-
"syncData": "Sync Local Data",
|
|
31
|
-
"syncDataDescription": "Upload your local data to the cloud",
|
|
32
|
-
"syncSuccess": "Data synced successfully",
|
|
33
|
-
"syncFailed": "Failed to sync data"
|
|
34
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cancel": "Cancel",
|
|
3
|
-
"confirm": "Confirm",
|
|
4
|
-
"continue": "Continue",
|
|
5
|
-
"delete": "Delete",
|
|
6
|
-
"edit": "Edit",
|
|
7
|
-
"error": "Error",
|
|
8
|
-
"loading": "Loading...",
|
|
9
|
-
"notNow": "Not Now",
|
|
10
|
-
"ok": "OK",
|
|
11
|
-
"optional": "Optional",
|
|
12
|
-
"save": "Save",
|
|
13
|
-
"somethingWentWrong": "Something went wrong",
|
|
14
|
-
"success": "Success",
|
|
15
|
-
"close": "Close",
|
|
16
|
-
"done": "Done",
|
|
17
|
-
"next": "Next",
|
|
18
|
-
"previous": "Previous",
|
|
19
|
-
"skip": "Skip",
|
|
20
|
-
"retry": "Retry",
|
|
21
|
-
"refresh": "Refresh",
|
|
22
|
-
"filter": "Filter",
|
|
23
|
-
"sort": "Sort",
|
|
24
|
-
"add": "Add",
|
|
25
|
-
"remove": "Remove",
|
|
26
|
-
"update": "Update",
|
|
27
|
-
"create": "Create",
|
|
28
|
-
"view": "View",
|
|
29
|
-
"details": "Details",
|
|
30
|
-
"share": "Share",
|
|
31
|
-
"download": "Download",
|
|
32
|
-
"upload": "Upload",
|
|
33
|
-
"submit": "Submit",
|
|
34
|
-
"reset": "Reset",
|
|
35
|
-
"clear": "Clear",
|
|
36
|
-
"apply": "Apply",
|
|
37
|
-
"yes": "Yes",
|
|
38
|
-
"no": "No",
|
|
39
|
-
"or": "or",
|
|
40
|
-
"all": "All",
|
|
41
|
-
"none": "None",
|
|
42
|
-
"of": "of",
|
|
43
|
-
"select": "Select",
|
|
44
|
-
"selected": "Selected",
|
|
45
|
-
"required": "Required",
|
|
46
|
-
"empty": "Empty",
|
|
47
|
-
"noData": "No data available",
|
|
48
|
-
"noResults": "No results found",
|
|
49
|
-
"tryAgain": "Try again",
|
|
50
|
-
"learnMore": "Learn more",
|
|
51
|
-
"getStarted": "Get started",
|
|
52
|
-
"viewAll": "View all",
|
|
53
|
-
"showMore": "Show more",
|
|
54
|
-
"showLess": "Show less",
|
|
55
|
-
"back": "Back",
|
|
56
|
-
"start": "Start"
|
|
57
|
-
}
|