Added translations

This commit is contained in:
xavis 2025-07-30 16:59:58 +02:00
parent 27bcd339ea
commit 5e91df4529
18 changed files with 362 additions and 35 deletions

View File

@ -55,13 +55,8 @@ EX_DEV_CLIENT_NETWORK_INSPECTOR=true
# Use legacy packaging to compress native libraries in the resulting APK.
expo.useLegacyPackaging=false
# Whether the app is configured to use edge-to-edge via the app config or `react-native-edge-to-edge` plugin
expo.edgeToEdgeEnabled=true
android.packagingOptions.pickFirsts=**/libc++_shared.so
expo.sqlite.enableFTS=false
expo.sqlite.useSQLCipher=false
MYAPP_UPLOAD_STORE_FILE=taskeep.keystore
MYAPP_UPLOAD_KEY_ALIAS=taskeep
MYAPP_UPLOAD_STORE_PASSWORD=123?_Tk_?123
MYAPP_UPLOAD_KEY_PASSWORD=123?_Tk_?123
# Whether the app is configured to use edge-to-edge via the app config or `react-native-edge-to-edge` plugin
expo.edgeToEdgeEnabled=true

View File

@ -3,10 +3,12 @@ import React from 'react';
import { Platform } from 'react-native';
import Ionicons from '@expo/vector-icons/Ionicons';
import { useTranslation } from 'react-i18next';
import { HapticTab } from '../../components/HapticTab';
import TabBarBackground from '../../components/ui/TabBarBackground';
export default function TabLayout() {
const { t } = useTranslation();
return (
<Tabs
@ -27,14 +29,14 @@ export default function TabLayout() {
<Tabs.Screen
name="index"
options={{
title: 'Tasks',
title: t('Tasks'),
tabBarIcon: ({ color }) => <Ionicons size={28} name="document-text-outline" color={color} />,
}}
/>
<Tabs.Screen
name="categories"
options={{
title: 'Categories',
title: t('Categories'),
tabBarIcon: ({ color }) => <Ionicons size={28} name="albums-outline" color={color} />,
}}
/>

View File

@ -5,7 +5,6 @@ import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import 'react-native-reanimated';
import "../i18n.js";
import React from 'react';
import { useColorScheme } from '../hooks/useColorScheme';

View File

@ -84,7 +84,7 @@ export default function TasksForm() {
useFocusEffect(React.useCallback(() => {
categoryRepository.findAll().then((categories) => {
categories.push(new Category("Create new category", "", 0));
categories.push(new Category(t("create_new_category"), "", 0));
setCategories(categories);
if (newTask.category === 0) {
setNewTask({ ...newTask, category: -1 });
@ -123,7 +123,7 @@ export default function TasksForm() {
/>
<View style={{ flexDirection: 'row', gap: 8, height: 60 }}>
<TextInput
placeholder={`${timeUnits.find(unit => unit.value === selectedTimeUnit)?.label} ${t('after_which_task_is_due')}`}
placeholder={`${t(timeUnits.find(unit => unit.value === selectedTimeUnit)?.label!)} ${t('after_which_task_is_due')}`}
style={styles.inputText}
placeholderTextColor="#333"
keyboardType='numeric'
@ -131,7 +131,12 @@ export default function TasksForm() {
onChange={(e) => setNewTask({ ...newTask, daysToRedo: e.nativeEvent.text.length > 0 ? parseInt(e.nativeEvent.text) : NaN })}
/>
<Dropdown
options={timeUnits}
options={timeUnits.map((tu) => {
return {
label: t(tu.label),
value: tu.value
}
})}
onValueChange={(value) => setSelectedTimeUnit(value?.toString() ?? "")}
selectedValue={selectedTimeUnit}
maxSelectableItems={1}
@ -208,18 +213,18 @@ export default function TasksForm() {
...task,
...newTask
}).then(() => {
toast.success("Task updated successfully!");
toast.success(t('task_updated_successfully'));
router.back();
});
} else {
// Create new task
taskRepository.create(new Task(newTask.title, newTask.daysToRedo, newTask.category)).then(() => {
toast.success("Task added successfully!");
toast.success(t('task_added_successfully'));
router.back();
});
}
} else {
toast.error("Please fill in all fields correctly.");
toast.error(t("please_fill_in_all_fields_correctly"));
}
}}>
<Ionicons name='checkmark-circle-outline' size={24} color="#fff" />

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { ColorProp, FlexWidget, IconWidget, ListWidget, SvgWidget, TextWidget, } from 'react-native-android-widget';
import { getClockProgressSVG } from '../../components/clockProgress';
import i18n from '../../i18n.js';
import { Category } from '../../models/category';
import { Task } from '../../models/task';
import { GetTaskColor } from '../../utils/colors';
@ -17,7 +17,8 @@ const adaptDaysToGoToUnit = (t: Task) => {
};
export function HelloWidget({ tasks, categories }: { tasks: Task[], categories?: Category[] }) {
const { t } = useTranslation();
const { t } = i18n;
const demoTasks: Task[] = [
new Task('Task 1', 1, 1, new Date().getTime() - 1000 * 60 * 60 * 24 * 0, 5), // 2 days ago

View File

@ -91,7 +91,7 @@ export function TaskItem({ task, categories, onUpdate, lightColor, darkColor, ..
{task?.title}
</Text>
<Text style={styles(colorScheme).taskItemText}>
{category?.icon + " " + category?.title + " - " + (adaptDaysToGoToUnit(task) == 0 ? "Overdue" : adaptDaysToGoToUnit(task))}
{category?.icon + " " + category?.title + " - " + (adaptDaysToGoToUnit(task) == 0 ? t("Overdue") : adaptDaysToGoToUnit(task))}
</Text>
</ThemedView>
<Pressable style={styles(colorScheme).checkButton} onPress={() => {

14
i18n.js
View File

@ -1,4 +1,4 @@
import * as Localization from 'expo-localization';
import { getLocales } from 'expo-localization';
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import ar from './translations/ar.json';
@ -12,16 +12,20 @@ import pt from './translations/pt.json';
import ru from './translations/ru.json';
import zh from './translations/zh.json';
registerWidgetTaskHandler(widgetTaskHandler);
// Initialize i18n
const resources = { en, es, fr, de, it, pt, zh, ja, ru, ar };
const langList = { en, es, fr, de, it, pt, zh, ja, ru, ar };
const resources = {};
const locales = getLocales();
Object.keys(langList).forEach((lang) => {
resources[lang] = { translation: langList[lang] };
});
i18n
.use(initReactI18next)
.init({
resources,
lng: Localization.locale.split('-')[0], // Use the device's language
lng: locales[0]?.languageTag.split('-')[0], // Use the device's language
fallbackLng: 'en',
interpolation: {
escapeValue: false, // React already escapes values

View File

@ -1,6 +1,7 @@
import 'expo-router/entry';
import { registerWidgetTaskHandler } from 'react-native-android-widget';
import { widgetTaskHandler } from './app/widgets/widget-task-handler';
import "./i18n.js";
registerWidgetTaskHandler(widgetTaskHandler);

View File

@ -29,5 +29,37 @@
"hello_tasks": "مرحبًا، المهام!",
"no_tasks_created": "لم يتم إنشاء مهام.",
"left": "متبقي",
"overdue": "متأخر"
"overdue": "متأخر",
"select_action": "اختر إجراءً",
"choose_action_for_task": "اختر إجراءً لهذه المهمة",
"choose_action_for_category": "اختر إجراءً لهذه الفئة",
"edit": "تحرير",
"remove": "إزالة",
"cancel": "إلغاء",
"select_icon": "اختر رمزًا",
"change_icon": "تغيير الرمز",
"select_iconand_enter_title": "اختر رمزًا وأدخل عنوانًا",
"add_category": "إضافة فئة",
"add_task": "إضافة مهمة",
"update_category": "تحديث الفئة",
"update_task": "تحديث المهمة",
"task_updated_successfully": "تم تحديث المهمة بنجاح!",
"category_updated_successfully": "تم تحديث الفئة بنجاح!",
"error_updating_task": "خطأ أثناء تحديث المهمة:",
"error_updating_category": "خطأ أثناء تحديث الفئة:",
"task_added_successfully": "تمت إضافة المهمة بنجاح!",
"category_added_successfully": "تمت إضافة الفئة بنجاح!",
"please_fill_in_all_fields_correctly": "يرجى ملء جميع الحقول بشكل صحيح.",
"task_deleted_successfully": "تم حذف المهمة بنجاح!",
"category_deleted_successfully": "تم حذف الفئة بنجاح!",
"create_new_category": "إنشاء فئة جديدة",
"after_which_task_is_due": "بعد ذلك تكون المهمة مستحقة",
"Minutes": "دقائق",
"Hours": "ساعات",
"Days": "أيام",
"Weeks": "أسابيع",
"Months": "أشهر",
"select_icon_and_enter_title": "اختر رمزًا وأدخل عنوانًا",
"Tasks": "المهام",
"Categories": "الفئات"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "Hallo, Aufgaben!",
"no_tasks_created": "Keine Aufgaben erstellt.",
"left": "verbleibend",
"overdue": "Überfällig"
"overdue": "Überfällig",
"select_action": "Wählen Sie eine Aktion",
"choose_action_for_task": "Wählen Sie eine Aktion für diese Aufgabe",
"choose_action_for_category": "Wählen Sie eine Aktion für diese Kategorie",
"edit": "Bearbeiten",
"remove": "Entfernen",
"cancel": "Abbrechen",
"select_icon": "Symbol auswählen",
"change_icon": "Symbol ändern",
"select_iconand_enter_title": "Wählen Sie ein Symbol und geben Sie einen Titel ein",
"add_category": "Kategorie hinzufügen",
"add_task": "Aufgabe hinzufügen",
"update_category": "Kategorie aktualisieren",
"update_task": "Aufgabe aktualisieren",
"task_updated_successfully": "Aufgabe erfolgreich aktualisiert!",
"category_updated_successfully": "Kategorie erfolgreich aktualisiert!",
"error_updating_task": "Fehler beim Aktualisieren der Aufgabe:",
"error_updating_category": "Fehler beim Aktualisieren der Kategorie:",
"task_added_successfully": "Aufgabe erfolgreich hinzugefügt!",
"category_added_successfully": "Kategorie erfolgreich hinzugefügt!",
"please_fill_in_all_fields_correctly": "Bitte füllen Sie alle Felder korrekt aus.",
"task_deleted_successfully": "Aufgabe erfolgreich gelöscht!",
"category_deleted_successfully": "Kategorie erfolgreich gelöscht!",
"create_new_category": "Neue Kategorie erstellen",
"after_which_task_is_due": "nachdem die Aufgabe fällig ist",
"Minutes": "Minuten",
"Hours": "Stunden",
"Days": "Tage",
"Weeks": "Wochen",
"Months": "Monate",
"select_icon_and_enter_title": "Wählen Sie ein Symbol und geben Sie einen Titel ein",
"Tasks": "Aufgaben",
"Categories": "Kategorien"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "Hello, Tasks!",
"no_tasks_created": "No tasks created.",
"left": "left",
"overdue": "Overdue"
"overdue": "Overdue",
"select_action": "Select an action",
"choose_action_for_task": "Choose an action for this task",
"choose_action_for_category": "Choose an action for this category",
"edit": "Edit",
"remove": "Remove",
"cancel": "Cancel",
"select_icon": "Select an icon",
"change_icon": "Change icon",
"select_iconand_enter_title": "Select an icon and enter a title",
"add_category": "Add Category",
"add_task": "Add Task",
"update_category": "Update Category",
"update_task": "Update Task",
"task_updated_successfully": "Task updated successfully!",
"category_updated_successfully": "Category updated successfully!",
"error_updating_task": "Error updating task:",
"error_updating_category": "Error updating category:",
"task_added_successfully": "Task added successfully!",
"category_added_successfully": "Category added successfully!",
"please_fill_in_all_fields_correctly": "Please fill in all fields correctly.",
"task_deleted_successfully": "Task deleted successfully!",
"category_deleted_successfully": "Category deleted successfully!",
"create_new_category": "Create new category",
"after_which_task_is_due": "after which task is due",
"Minutes": "Minutes",
"Hours": "Hours",
"Days": "Days",
"Weeks": "Weeks",
"Months": "Months",
"select_icon_and_enter_title": "Select an icon and enter a title",
"Tasks": "Tasks",
"Categories": "Categories"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "¡Hola, Tareas!",
"no_tasks_created": "No se han creado tareas.",
"left": "restante",
"overdue": "Atrasado"
"overdue": "Atrasado",
"select_action": "Selecciona una acción",
"choose_action_for_task": "Elige una acción para esta tarea",
"choose_action_for_category": "Elige una acción para esta categoría",
"edit": "Editar",
"remove": "Eliminar",
"cancel": "Cancelar",
"select_icon": "Seleccionar un ícono",
"change_icon": "Cambiar ícono",
"select_iconand_enter_title": "Selecciona un ícono e ingresa un título",
"add_category": "Agregar Categoría",
"add_task": "Agregar Tarea",
"update_category": "Actualizar Categoría",
"update_task": "Actualizar Tarea",
"task_updated_successfully": "¡Tarea actualizada con éxito!",
"category_updated_successfully": "¡Categoría actualizada con éxito!",
"error_updating_task": "Error al actualizar la tarea:",
"error_updating_category": "Error al actualizar la categoría:",
"task_added_successfully": "¡Tarea añadida con éxito!",
"category_added_successfully": "¡Categoría añadida con éxito!",
"please_fill_in_all_fields_correctly": "Por favor, completa todos los campos correctamente.",
"task_deleted_successfully": "¡Tarea eliminada con éxito!",
"category_deleted_successfully": "¡Categoría eliminada con éxito!",
"create_new_category": "Crear nueva categoría",
"after_which_task_is_due": "después de lo cual vence la tarea",
"Minutes": "Minutos",
"Hours": "Horas",
"Days": "Días",
"Weeks": "Semanas",
"Months": "Meses",
"select_icon_and_enter_title": "Selecciona un ícono e ingresa un título",
"Tasks": "Tareas",
"Categories": "Categorías"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "Bonjour, Tâches!",
"no_tasks_created": "Aucune tâche créée.",
"left": "restant",
"overdue": "En retard"
"overdue": "En retard",
"select_action": "Sélectionnez une action",
"choose_action_for_task": "Choisissez une action pour cette tâche",
"choose_action_for_category": "Choisissez une action pour cette catégorie",
"edit": "Modifier",
"remove": "Supprimer",
"cancel": "Annuler",
"select_icon": "Sélectionner une icône",
"change_icon": "Changer d'icône",
"select_iconand_enter_title": "Sélectionnez une icône et entrez un titre",
"add_category": "Ajouter une catégorie",
"add_task": "Ajouter une tâche",
"update_category": "Mettre à jour la catégorie",
"update_task": "Mettre à jour la tâche",
"task_updated_successfully": "Tâche mise à jour avec succès!",
"category_updated_successfully": "Catégorie mise à jour avec succès!",
"error_updating_task": "Erreur lors de la mise à jour de la tâche:",
"error_updating_category": "Erreur lors de la mise à jour de la catégorie:",
"task_added_successfully": "Tâche ajoutée avec succès!",
"category_added_successfully": "Catégorie ajoutée avec succès!",
"please_fill_in_all_fields_correctly": "Veuillez remplir tous les champs correctement.",
"task_deleted_successfully": "Tâche supprimée avec succès!",
"category_deleted_successfully": "Catégorie supprimée avec succès!",
"create_new_category": "Créer une nouvelle catégorie",
"after_which_task_is_due": "après quoi la tâche est due",
"Minutes": "Minutes",
"Hours": "Heures",
"Days": "Jours",
"Weeks": "Semaines",
"Months": "Mois",
"select_icon_and_enter_title": "Sélectionnez une icône et entrez un titre",
"Tasks": "Tâches",
"Categories": "Catégories"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "Ciao, Attività!",
"no_tasks_created": "Nessuna attività creata.",
"left": "rimanente",
"overdue": "In ritardo"
"overdue": "In ritardo",
"select_action": "Seleziona un'azione",
"choose_action_for_task": "Scegli un'azione per questa attività",
"choose_action_for_category": "Scegli un'azione per questa categoria",
"edit": "Modifica",
"remove": "Rimuovi",
"cancel": "Annulla",
"select_icon": "Seleziona un'icona",
"change_icon": "Cambia icona",
"select_iconand_enter_title": "Seleziona un'icona e inserisci un titolo",
"add_category": "Aggiungi Categoria",
"add_task": "Aggiungi Attività",
"update_category": "Aggiorna Categoria",
"update_task": "Aggiorna Attività",
"task_updated_successfully": "Attività aggiornata con successo!",
"category_updated_successfully": "Categoria aggiornata con successo!",
"error_updating_task": "Errore durante l'aggiornamento dell'attività:",
"error_updating_category": "Errore durante l'aggiornamento della categoria:",
"task_added_successfully": "Attività aggiunta con successo!",
"category_added_successfully": "Categoria aggiunta con successo!",
"please_fill_in_all_fields_correctly": "Si prega di compilare correttamente tutti i campi.",
"task_deleted_successfully": "Attività eliminata con successo!",
"category_deleted_successfully": "Categoria eliminata con successo!",
"create_new_category": "Crea nuova categoria",
"after_which_task_is_due": "dopo di che l'attività è dovuta",
"Minutes": "Minuti",
"Hours": "Ore",
"Days": "Giorni",
"Weeks": "Settimane",
"Months": "Mesi",
"select_icon_and_enter_title": "Seleziona un'icona e inserisci un titolo",
"Tasks": "Attività",
"Categories": "Categorie"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "こんにちは、タスク!",
"no_tasks_created": "タスクが作成されていません。",
"left": "残り",
"overdue": "期限切れ"
"overdue": "期限切れ",
"select_action": "アクションを選択",
"choose_action_for_task": "このタスクのアクションを選択",
"choose_action_for_category": "このカテゴリのアクションを選択",
"edit": "編集",
"remove": "削除",
"cancel": "キャンセル",
"select_icon": "アイコンを選択",
"change_icon": "アイコンを変更",
"select_iconand_enter_title": "アイコンを選択してタイトルを入力",
"add_category": "カテゴリを追加",
"add_task": "タスクを追加",
"update_category": "カテゴリを更新",
"update_task": "タスクを更新",
"task_updated_successfully": "タスクが正常に更新されました!",
"category_updated_successfully": "カテゴリが正常に更新されました!",
"error_updating_task": "タスクの更新中にエラーが発生しました:",
"error_updating_category": "カテゴリの更新中にエラーが発生しました:",
"task_added_successfully": "タスクが正常に追加されました!",
"category_added_successfully": "カテゴリが正常に追加されました!",
"please_fill_in_all_fields_correctly": "すべてのフィールドを正しく入力してください。",
"task_deleted_successfully": "タスクが正常に削除されました!",
"category_deleted_successfully": "カテゴリが正常に削除されました!",
"create_new_category": "新しいカテゴリを作成",
"after_which_task_is_due": "タスクが期限になるまで",
"Minutes": "分",
"Hours": "時間",
"Days": "日",
"Weeks": "週間",
"Months": "月",
"select_icon_and_enter_title": "アイコンを選択してタイトルを入力",
"Tasks": "タスク",
"Categories": "カテゴリ"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "Olá, Tarefas!",
"no_tasks_created": "Nenhuma tarefa criada.",
"left": "restante",
"overdue": "Atrasado"
"overdue": "Atrasado",
"select_action": "Selecione uma ação",
"choose_action_for_task": "Escolha uma ação para esta tarefa",
"choose_action_for_category": "Escolha uma ação para esta categoria",
"edit": "Editar",
"remove": "Remover",
"cancel": "Cancelar",
"select_icon": "Selecionar um ícone",
"change_icon": "Alterar ícone",
"select_iconand_enter_title": "Selecione um ícone e insira um título",
"add_category": "Adicionar Categoria",
"add_task": "Adicionar Tarefa",
"update_category": "Atualizar Categoria",
"update_task": "Atualizar Tarefa",
"task_updated_successfully": "Tarefa atualizada com sucesso!",
"category_updated_successfully": "Categoria atualizada com sucesso!",
"error_updating_task": "Erro ao atualizar a tarefa:",
"error_updating_category": "Erro ao atualizar a categoria:",
"task_added_successfully": "Tarefa adicionada com sucesso!",
"category_added_successfully": "Categoria adicionada com sucesso!",
"please_fill_in_all_fields_correctly": "Por favor, preencha todos os campos corretamente.",
"task_deleted_successfully": "Tarefa excluída com sucesso!",
"category_deleted_successfully": "Categoria excluída com sucesso!",
"create_new_category": "Criar nova categoria",
"after_which_task_is_due": "após o qual a tarefa é devida",
"Minutes": "Minutos",
"Hours": "Horas",
"Days": "Dias",
"Weeks": "Semanas",
"Months": "Meses",
"select_icon_and_enter_title": "Selecione um ícone e insira um título",
"Tasks": "Tarefas",
"Categories": "Categorias"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "Привет, задачи!",
"no_tasks_created": "Задачи не созданы.",
"left": "осталось",
"overdue": "Просрочено"
"overdue": "Просрочено",
"select_action": "Выберите действие",
"choose_action_for_task": "Выберите действие для этой задачи",
"choose_action_for_category": "Выберите действие для этой категории",
"edit": "Редактировать",
"remove": "Удалить",
"cancel": "Отмена",
"select_icon": "Выберите значок",
"change_icon": "Изменить значок",
"select_iconand_enter_title": "Выберите значок и введите название",
"add_category": "Добавить категорию",
"add_task": "Добавить задачу",
"update_category": "Обновить категорию",
"update_task": "Обновить задачу",
"task_updated_successfully": "Задача успешно обновлена!",
"category_updated_successfully": "Категория успешно обновлена!",
"error_updating_task": "Ошибка при обновлении задачи:",
"error_updating_category": "Ошибка при обновлении категории:",
"task_added_successfully": "Задача успешно добавлена!",
"category_added_successfully": "Категория успешно добавлена!",
"please_fill_in_all_fields_correctly": "Пожалуйста, заполните все поля правильно.",
"task_deleted_successfully": "Задача успешно удалена!",
"category_deleted_successfully": "Категория успешно удалена!",
"create_new_category": "Создать новую категорию",
"after_which_task_is_due": "после чего задача должна быть выполнена",
"Minutes": "Минуты",
"Hours": "Часы",
"Days": "Дни",
"Weeks": "Недели",
"Months": "Месяцы",
"select_icon_and_enter_title": "Выберите значок и введите название",
"Tasks": "Задачи",
"Categories": "Категории"
}

View File

@ -29,5 +29,37 @@
"hello_tasks": "你好,任务!",
"no_tasks_created": "没有创建任务。",
"left": "剩余",
"overdue": "逾期"
"overdue": "逾期",
"select_action": "选择一个操作",
"choose_action_for_task": "为此任务选择一个操作",
"choose_action_for_category": "为此类别选择一个操作",
"edit": "编辑",
"remove": "移除",
"cancel": "取消",
"select_icon": "选择一个图标",
"change_icon": "更改图标",
"select_iconand_enter_title": "选择一个图标并输入标题",
"add_category": "添加类别",
"add_task": "添加任务",
"update_category": "更新类别",
"update_task": "更新任务",
"task_updated_successfully": "任务更新成功!",
"category_updated_successfully": "类别更新成功!",
"error_updating_task": "更新任务时出错:",
"error_updating_category": "更新类别时出错:",
"task_added_successfully": "任务添加成功!",
"category_added_successfully": "类别添加成功!",
"please_fill_in_all_fields_correctly": "请正确填写所有字段。",
"task_deleted_successfully": "任务删除成功!",
"category_deleted_successfully": "类别删除成功!",
"create_new_category": "创建新类别",
"after_which_task_is_due": "任务到期后",
"Minutes": "分钟",
"Hours": "小时",
"Days": "天",
"Weeks": "周",
"Months": "月",
"select_icon_and_enter_title": "选择一个图标并输入标题",
"Tasks": "任务",
"Categories": "类别"
}