feat(i18n): add Russian locale
This commit is contained in:
1 parent
84ec5eac74
commit
0b3e79331b
12 files changed
+11853
-7
No files matched your search
+1
-1
@@ -2,7 +2,7 @@ import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const source = readFileSync(new URL("../AiAssistant.vue", import.meta.url), "utf8");
|
||||
const localePaths = ["az", "en", "es", "it", "ja", "ko", "pt-BR", "tr", "zh-CN", "zh-TW"];
|
||||
const localePaths = ["az", "en", "es", "it", "ja", "ko", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"];
|
||||
|
||||
describe("AI assistant write confirmation replacement", () => {
|
||||
it("renders a localized confirmation from the backend's semantic event", () => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import it from "@/i18n/locales/it";
|
||||
import ja from "@/i18n/locales/ja";
|
||||
import ko from "@/i18n/locales/ko";
|
||||
import ptBR from "@/i18n/locales/pt-BR";
|
||||
import ru from "@/i18n/locales/ru";
|
||||
import tr from "@/i18n/locales/tr";
|
||||
import zhCN from "@/i18n/locales/zh-CN";
|
||||
import zhTW from "@/i18n/locales/zh-TW";
|
||||
@@ -23,6 +24,7 @@ const LOCALES = {
|
||||
ja,
|
||||
ko,
|
||||
"pt-BR": ptBR,
|
||||
ru,
|
||||
tr,
|
||||
"zh-CN": zhCN,
|
||||
"zh-TW": zhTW,
|
||||
|
||||
@@ -6,6 +6,7 @@ import it_ from "../locales/docs/it";
|
||||
import ja from "../locales/docs/ja";
|
||||
import ko from "../locales/docs/ko";
|
||||
import ptBR from "../locales/docs/pt-BR";
|
||||
import ru from "../locales/docs/ru";
|
||||
import tr from "../locales/docs/tr";
|
||||
import zhCN from "../locales/docs/zh-CN";
|
||||
import zhTW from "../locales/docs/zh-TW";
|
||||
@@ -24,6 +25,7 @@ const locales: Array<[string, Record<string, unknown>]> = [
|
||||
["ja", ja],
|
||||
["ko", ko],
|
||||
["pt-BR", ptBR],
|
||||
["ru", ru],
|
||||
["tr", tr],
|
||||
["zh-CN", zhCN],
|
||||
["zh-TW", zhTW],
|
||||
|
||||
+3
-2
@@ -7,6 +7,7 @@ import itLocale from "../locales/it";
|
||||
import ja from "../locales/ja";
|
||||
import ko from "../locales/ko";
|
||||
import ptBR from "../locales/pt-BR";
|
||||
import ru from "../locales/ru";
|
||||
import tr from "../locales/tr";
|
||||
import zhCN from "../locales/zh-CN";
|
||||
import zhTW from "../locales/zh-TW";
|
||||
@@ -19,9 +20,9 @@ import zhTW from "../locales/zh-TW";
|
||||
vi.mock("../locales/fallback", () => ({ withEnglishFallback: (messages: Record<string, unknown>) => messages }));
|
||||
|
||||
type Messages = Record<string, unknown>;
|
||||
type Locale = "az" | "en" | "es" | "it" | "ja" | "ko" | "pt-BR" | "tr" | "zh-CN" | "zh-TW";
|
||||
type Locale = "az" | "en" | "es" | "it" | "ja" | "ko" | "pt-BR" | "ru" | "tr" | "zh-CN" | "zh-TW";
|
||||
|
||||
const declared: Record<Locale, Messages> = { az, en, es, it: itLocale, ja, ko, "pt-BR": ptBR, tr, "zh-CN": zhCN, "zh-TW": zhTW };
|
||||
const declared: Record<Locale, Messages> = { az, en, es, it: itLocale, ja, ko, "pt-BR": ptBR, ru, tr, "zh-CN": zhCN, "zh-TW": zhTW };
|
||||
const ALL_LOCALES = Object.keys(declared) as Locale[];
|
||||
const EXCEPT_AZ_TR = ALL_LOCALES.filter((locale) => locale !== "az" && locale !== "tr");
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@ import en from "./locales/en";
|
||||
import { safeLocalStorageGet, safeLocalStorageSet } from "@/lib/backend/safeStorage";
|
||||
import { isTauriRuntime } from "@/lib/backend/tauriRuntime";
|
||||
|
||||
export type Locale = "az" | "en" | "es" | "it" | "ja" | "ko" | "pt-BR" | "tr" | "zh-CN" | "zh-TW";
|
||||
export type Locale = "az" | "en" | "es" | "it" | "ja" | "ko" | "pt-BR" | "ru" | "tr" | "zh-CN" | "zh-TW";
|
||||
type LocaleMessages = Record<string, unknown>;
|
||||
type I18nGlobal = {
|
||||
locale: { value: Locale };
|
||||
setLocaleMessage: (locale: Locale, messages: LocaleMessages) => void;
|
||||
};
|
||||
|
||||
const supportedLocales: Locale[] = ["az", "en", "es", "it", "ja", "ko", "pt-BR", "tr", "zh-CN", "zh-TW"];
|
||||
const supportedLocales: Locale[] = ["az", "en", "es", "it", "ja", "ko", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"];
|
||||
const defaultLocale: Locale = "en";
|
||||
const loadedLocales = new Set<Locale>([defaultLocale]);
|
||||
const localeLoaders: Record<Exclude<Locale, "en">, () => Promise<{ default: LocaleMessages }>> = {
|
||||
@@ -20,6 +20,7 @@ const localeLoaders: Record<Exclude<Locale, "en">, () => Promise<{ default: Loca
|
||||
ja: () => import("./locales/ja"),
|
||||
ko: () => import("./locales/ko"),
|
||||
"pt-BR": () => import("./locales/pt-BR"),
|
||||
ru: () => import("./locales/ru"),
|
||||
tr: () => import("./locales/tr"),
|
||||
"zh-CN": () => import("./locales/zh-CN"),
|
||||
"zh-TW": () => import("./locales/zh-TW"),
|
||||
@@ -48,6 +49,7 @@ export function localeFromLanguageTag(value: string | null | undefined): Locale
|
||||
if (normalized === "ja" || normalized.startsWith("ja-")) return "ja";
|
||||
if (normalized === "ko" || normalized.startsWith("ko-")) return "ko";
|
||||
if (normalized === "pt" || normalized.startsWith("pt-")) return "pt-BR";
|
||||
if (normalized === "ru" || normalized.startsWith("ru-")) return "ru";
|
||||
if (normalized === "tr" || normalized.startsWith("tr-")) return "tr";
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
export default {
|
||||
title: "Документация",
|
||||
groupBySchema: "Схемы",
|
||||
groupByTableGroup: "Группы таблиц",
|
||||
noGroup: "(без группы)",
|
||||
noSchema: "(без схемы)",
|
||||
search: "Поиск таблиц, столбцов, групп…",
|
||||
columns: "Столбцы",
|
||||
indexes: "Индексы",
|
||||
references: "Ссылки",
|
||||
referencedBy: "Ссылаются на",
|
||||
localNote: "ЛОКАЛЬНО",
|
||||
shadowedComment: "Комментарий базы данных: {comment}",
|
||||
addNote: "Добавить заметку",
|
||||
editNote: "Редактировать заметку",
|
||||
newGroup: "Новая группа…",
|
||||
groupName: "Название группы",
|
||||
groupColour: "Цвет",
|
||||
deleteGroup: "Удалить группу",
|
||||
enumValues: "Значения",
|
||||
usedBy: "Используется в",
|
||||
openDiagram: "Открыть схему",
|
||||
saving: "Сохранение…",
|
||||
saved: "Сохранено",
|
||||
saveFailed: "Не удалось сохранить заметки: {error}",
|
||||
overview: "Обзор",
|
||||
groupBy: "Группировать по",
|
||||
searchLabel: "Поиск",
|
||||
groups: "Группы",
|
||||
relationships: "Связи",
|
||||
columnHeader: "Столбец",
|
||||
typeHeader: "Тип",
|
||||
settingsHeader: "Настройки",
|
||||
noteHeader: "Заметка",
|
||||
nameHeader: "Имя",
|
||||
definitionHeader: "Определение",
|
||||
noOutgoingRelationships: "Эта таблица не ссылается на другие таблицы.",
|
||||
noIncomingRelationships: "Ни одна таблица не ссылается на эту.",
|
||||
diagram: "Диаграмма",
|
||||
language: "Язык",
|
||||
theme: "Тема",
|
||||
themeLight: "Светлая",
|
||||
themeDark: "Тёмная",
|
||||
exportHtml: "Экспорт в HTML…",
|
||||
exporting: "Экспорт…",
|
||||
exportFailed: "Не удалось выполнить экспорт: {error}",
|
||||
warnings: {
|
||||
tableSkipped: {
|
||||
title: "Не удалось задокументировать таблицу",
|
||||
detail: "{table} пропущена: {reason}. Её нет в этой документации.",
|
||||
},
|
||||
noForeignKeyMetadata: {
|
||||
title: "Связи недоступны",
|
||||
detail: "{engine} не сообщает метаданные внешних ключей, поэтому связи не удалось построить. Для этого движка диаграмма полная.",
|
||||
},
|
||||
commentsUnsupported: {
|
||||
title: "Комментарии базы данных недоступны",
|
||||
detail: "{engine} не поддерживает комментарии к таблицам и столбцам, поэтому все описания здесь взяты из собственных заметок проекта.",
|
||||
},
|
||||
orphanedNotes: {
|
||||
title: "Часть заметок больше ни с чем не связана",
|
||||
detail: "Заметок, ссылающихся на несуществующую таблицу или столбец: {count}. Ничего не удалено — измените привязку или удалите их в файле заметок.",
|
||||
},
|
||||
dbmlOmitted: {
|
||||
title: "Невозможно представить в DBML",
|
||||
detail: "{item} в {table} задокументирован здесь, но пропущен в экспортированном DBML: {reason}.",
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -457,6 +457,123 @@ export const meilisearchManagementMessages = {
|
||||
deleteTaskHistory: "Geçmişi sil",
|
||||
readOnlyDisabled: "Salt okunur bağlantılarda işlemler devre dışıdır.",
|
||||
},
|
||||
ru: {
|
||||
systemManagement: "Управление системой",
|
||||
overview: "Обзор",
|
||||
overviewDescription: "Состояние, ёмкость, индексы, ключи и активность задач в реальном времени.",
|
||||
apiKeys: "API-ключи",
|
||||
keysDescription: "Создание и управление ограниченными по области действия API-ключами Meilisearch.",
|
||||
tasks: "Задачи",
|
||||
tasksDescription: "Просмотр асинхронных операций, отмена активных задач и очистка завершённой истории.",
|
||||
health: "Состояние",
|
||||
version: "Версия",
|
||||
indexCount: "Индексы",
|
||||
totalDocuments: "Всего документов",
|
||||
indexingCount: "Индексация",
|
||||
keyCount: "Ключи",
|
||||
storage: "Хранилище",
|
||||
usedDatabaseSize: "Занято базой данных",
|
||||
lastUpdate: "Последнее обновление",
|
||||
taskStatusDistribution: "Распределение статусов задач",
|
||||
topIndexes: "Индексы с наибольшим числом документов",
|
||||
status: "Статус",
|
||||
idle: "Простой",
|
||||
sectionStatus: { available: "Доступно", forbidden: "Доступ запрещён", unsupported: "Не поддерживается этим сервером", error: "Недоступно" },
|
||||
refresh: "Обновить",
|
||||
rowActions: "Действия",
|
||||
previous: "Назад",
|
||||
next: "Вперёд",
|
||||
name: "Название",
|
||||
key: "Ключ",
|
||||
description: "Описание",
|
||||
actions: "Действия",
|
||||
indexes: "Индексы",
|
||||
expiresAt: "Срок действия",
|
||||
never: "Никогда",
|
||||
createKey: "Создать ключ",
|
||||
editKey: "Изменить ключ",
|
||||
deleteKey: "Удалить ключ",
|
||||
keyDetails: "Сведения о ключе",
|
||||
keyCreated: "API-ключ создан",
|
||||
keyUpdated: "API-ключ обновлён",
|
||||
keyDeleted: "API-ключ удалён",
|
||||
noKeys: "API-ключи не найдены",
|
||||
deleteKeyConfirm: "Удалить API-ключ {uid}? Это действие нельзя отменить.",
|
||||
deleteKeyTypePrompt: "Введите полный UID ключа, чтобы подтвердить удаление.",
|
||||
deleteKeyTypePlaceholder: "Введите UID ключа",
|
||||
immutableKeyFields: "Действия, индексы, срок действия, UID и секрет неизменяемы. Чтобы изменить их, создайте ключ заново.",
|
||||
secretShownOnce: "Скопируйте секрет сейчас. DBX никогда не сохраняет значения API-ключей.",
|
||||
actionsIndexesRequired: "Требуется указать хотя бы одно действие и один индекс.",
|
||||
uidPlaceholder: "Оставьте пустым, чтобы сгенерировать случайный UID",
|
||||
uidHelp: "Необязательно. Если оставить пустым, Meilisearch сгенерирует случайный UID.",
|
||||
namePlaceholder: "Укажите название ключа",
|
||||
nameHelp: "Необязательное название для идентификации этого ключа.",
|
||||
descriptionPlaceholder: "Добавьте необязательное описание",
|
||||
descriptionHelp: "Необязательная заметка о том, где и для чего используется ключ.",
|
||||
indexesPlaceholder: "Выберите разрешённые индексы",
|
||||
indexesHelp: "Выберите один или несколько доступных индексов. Значение * предоставляет доступ ко всем индексам.",
|
||||
actionsPlaceholder: "Выберите разрешённые действия",
|
||||
actionsHelp: "Выберите операции API, которые этот ключ разрешено выполнять.",
|
||||
expiresAtPlaceholder: "Выберите или введите дату и время",
|
||||
expiresAtHelp: "Необязательно. Оставьте пустым, чтобы срок действия не истекал, либо введите корректные дату и время.",
|
||||
openDateTimePicker: "Открыть выбор даты и времени",
|
||||
invalidExpiresAt: "Введите корректные дату и время окончания срока действия.",
|
||||
copyKeyValue: "Копировать API-ключ",
|
||||
paginationSummary: "{start}–{end} из {total}",
|
||||
readOnlyDisabled: "Это подключение доступно только для чтения; управляющие операции отключены.",
|
||||
filters: "Фильтры",
|
||||
applyFilters: "Применить фильтры",
|
||||
resetFilters: "Сбросить фильтры",
|
||||
uidFilter: "Фильтр по UID",
|
||||
searchUid: "Поиск по UID",
|
||||
allIndexes: "Все индексы",
|
||||
allStatuses: "Все статусы",
|
||||
indexListUnavailable: "Не удалось загрузить список доступных индексов",
|
||||
reverseOrder: "Обратный порядок",
|
||||
columnSettings: "Настроить столбцы",
|
||||
index: "Индекс",
|
||||
type: "Тип",
|
||||
details: "Подробности",
|
||||
receivedDocuments: "Получено документов",
|
||||
indexedDocuments: "Проиндексировано документов",
|
||||
enqueuedAt: "В очереди",
|
||||
startedAt: "Начато",
|
||||
finishedAt: "Завершено",
|
||||
duration: "Длительность",
|
||||
afterEnqueuedAt: "В очереди после",
|
||||
beforeEnqueuedAt: "В очереди до",
|
||||
afterStartedAt: "Начато после",
|
||||
beforeStartedAt: "Начато до",
|
||||
afterFinishedAt: "Завершено после",
|
||||
beforeFinishedAt: "Завершено до",
|
||||
indexTasks: "Задачи · {index}",
|
||||
noTasks: "Задачи не найдены",
|
||||
taskCount: "Подходящих задач: {count}",
|
||||
taskDetails: "Сведения о задаче",
|
||||
cancelTask: "Отменить задачу",
|
||||
cancelTasks: "Отменить задачи",
|
||||
deleteTaskHistory: "Удалить историю задач",
|
||||
cancelFilteredTasks: "Отменить отобранные активные задачи",
|
||||
deleteFilteredHistory: "Удалить отобранную завершённую историю",
|
||||
explicitFilterRequired: "Перед массовой операцией задайте хотя бы один явный фильтр.",
|
||||
noAllowedTaskStatuses: "В применённом фильтре нет статусов задач, разрешённых для этой операции.",
|
||||
countingMatchingTasks: "Подсчёт подходящих задач...",
|
||||
cancelTasksConfirm: "Отменить активные задачи, соответствующие этому фильтру (сейчас найдено: {count})?",
|
||||
deleteTasksConfirm: "Удалить завершённую историю задач, соответствующую этому фильтру (сейчас найдено: {count})?",
|
||||
waitingForTask: "Ожидание задачи управления #{uid}",
|
||||
taskOperationCompleted: "Операция с задачей завершена",
|
||||
taskOperationFinished: "Операция с задачей завершена со статусом {status}",
|
||||
taskPollingTimeout: "Задача #{uid} не завершилась за 60 секунд. Обновите страницу вручную, чтобы проверить её состояние.",
|
||||
taskOutsideIndex: "Эта задача не относится к текущему индексу.",
|
||||
createIndex: "Создать индекс",
|
||||
createIndexUid: "UID индекса",
|
||||
createIndexPrimaryKey: "Первичный ключ",
|
||||
indexCreated: "Индекс создан",
|
||||
createIndexUidRequired: "Укажите UID индекса.",
|
||||
createIndexUidPlaceholder: "Введите UID индекса",
|
||||
createIndexPrimaryKeyPlaceholder: "Необязательный первичный ключ",
|
||||
createIndexPrimaryKeyHelp: "Оставьте пустым, чтобы задать первичный ключ при добавлении первого документа.",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const meilisearchManagementAz = meilisearchManagementMessages.az;
|
||||
@@ -469,3 +586,4 @@ export const meilisearchManagementEs = meilisearchManagementMessages.es;
|
||||
export const meilisearchManagementIt = meilisearchManagementMessages.it;
|
||||
export const meilisearchManagementPtBR = meilisearchManagementMessages["pt-BR"];
|
||||
export const meilisearchManagementTr = meilisearchManagementMessages.tr;
|
||||
export const meilisearchManagementRu = meilisearchManagementMessages.ru;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -8,6 +8,7 @@ export const LOCALE_OPTIONS: { value: Locale; flag: string; label: string }[] =
|
||||
{ value: "ja", flag: "🇯🇵", label: "日本語" },
|
||||
{ value: "ko", flag: "🇰🇷", label: "한국어" },
|
||||
{ value: "pt-BR", flag: "🇧🇷", label: "Português" },
|
||||
{ value: "ru", flag: "🇷🇺", label: "Русский" },
|
||||
{ value: "tr", flag: "🇹🇷", label: "Türkçe" },
|
||||
{ value: "zh-CN", flag: "🇨🇳", label: "简体中文" },
|
||||
{ value: "zh-TW", flag: "繁", label: "繁體中文" },
|
||||
|
||||
Reference in new issue
Block a user