feat(i18n): raise translation coverage across all 20 locales (round 2) (#453)

An audit comparing every locale's leaf values against en.ts found
structural key-parity was already perfect (0 missing/extra keys), but
~2,356 leaf values across the 20 non-English locales were still
byte-identical to the English source, meaning they'd shipped untranslated.
The largest single cause: the feedback widget (PR #428) shipped with
English placeholder text in every locale except Italian, which had a
separate community translation (#425/#426).

Translates the 1,289 strings that were genuinely missing translations,
locale by locale, matching each file's own established register,
terminology, and loanword conventions (verified against already-translated
sibling strings rather than assumed). Leaves the remaining ~1,067 flagged
values untouched where they're legitimately identical to English: brand
names, format/protocol acronyms, literal URLs, hex colors, and terms this
project already treats as loanwords in that language.

Verified against current main: pnpm typecheck 0 errors (9/9 workspaces),
i18n-parity/i18n-locale/tool-i18n/template-i18n 45/45 passing (23/23
cross-locale parity), biome check clean.
This commit is contained in:
SnapOtter
2026-07-06 21:18:59 +08:00
committed by GitHub
parent 0fafeb2676
commit 44e1f90e4a
20 changed files with 1312 additions and 1291 deletions
+69 -68
View File
@@ -50,28 +50,29 @@ export const ru: TranslationKeys = {
pageNotFoundDescription: "Запрашиваемая страница не существует или была перемещена.",
},
feedback: {
navLabel: "Share feedback",
navLabel: "Поделиться отзывом",
navButtonLabel: "Отзыв",
dialogTitle: "Share feedback",
toolDialogTitle: "How did this tool work?",
failedDialogTitle: "Report a tool issue",
adminDialogTitle: "How was setup?",
closeLabel: "Close feedback dialog",
dialogTitle: "Поделиться отзывом",
toolDialogTitle: "Как сработал этот инструмент?",
failedDialogTitle: "Сообщить о проблеме с инструментом",
adminDialogTitle: "Как прошла установка?",
closeLabel: "Закрыть окно отзыва",
privacyNote:
"Feedback is sent only when you submit it. SnapOtter does not include your files, file contents, file names, or private outputs.",
typeLabel: "Feedback type",
sentimentLabel: "Quick rating",
messageLabel: "Feedback",
messagePlaceholder: "Tell us what worked, what broke, or what would make SnapOtter better.",
improveFirstLabel: "What should we improve first?",
improveFirstPlaceholder: "Tell us what made setup harder than it should be.",
contactOkLabel: "You can contact me about this feedback.",
emailPlaceholder: "Email (optional)",
namePlaceholder: "Name (optional)",
companyPlaceholder: "Company or org (optional)",
submit: "Send feedback",
submitting: "Sending...",
submitFailed: "Feedback could not be sent. Please try again.",
"Отзыв передаётся только после того, как вы его отправите. SnapOtter не включает ваши файлы, их содержимое, имена файлов и личные результаты.",
typeLabel: "Тип отзыва",
sentimentLabel: "Быстрая оценка",
messageLabel: "Отзыв",
messagePlaceholder:
"Расскажите, что сработало, что сломалось или что сделало бы SnapOtter лучше.",
improveFirstLabel: "Что нам улучшить в первую очередь?",
improveFirstPlaceholder: "Расскажите, из-за чего установка оказалась сложнее, чем нужно.",
contactOkLabel: "Со мной можно связаться по поводу этого отзыва.",
emailPlaceholder: "Эл. почта (необязательно)",
namePlaceholder: "Имя (необязательно)",
companyPlaceholder: "Компания или организация (необязательно)",
submit: "Отправить отзыв",
submitting: "Отправка...",
submitFailed: "Не удалось отправить отзыв. Попробуйте ещё раз.",
searchMissTitle: "Запросить инструмент",
searchMissContext: "Вы искали: {query}",
searchMissDiscussionsFallback: "Не удалось записать. Откройте запрос в Discussions.",
@@ -80,71 +81,71 @@ export const ru: TranslationKeys = {
offlinePublicNote: "Issue на GitHub публичны.",
offlineGithubButton: "Открыть issue на GitHub",
offlineEmailButton: "Напишите нам",
thanksTitle: "Thanks for the feedback.",
thanksDescription: "It helps us improve SnapOtter without collecting files or private content.",
quickThanks: "Thanks for the signal.",
reportIssue: "Report issue",
toolPromptTitle: "How did this tool work?",
toolPromptDescription: "One quick signal helps us improve SnapOtter.",
dismissPrompt: "Dismiss feedback prompt",
workedWell: "Worked well",
dontAskAgain: "Don't ask again",
shareFeedback: "Share feedback",
remindLater: "Remind me later",
adminCardTitle: "How was setup?",
thanksTitle: "Спасибо за отзыв.",
thanksDescription: "Это помогает нам улучшать SnapOtter, не собирая файлы и личные данные.",
quickThanks: "Спасибо за сигнал.",
reportIssue: "Сообщить о проблеме",
toolPromptTitle: "Как сработал этот инструмент?",
toolPromptDescription: "Один быстрый сигнал помогает нам улучшать SnapOtter.",
dismissPrompt: "Скрыть запрос отзыва",
workedWell: "Сработало хорошо",
dontAskAgain: "Больше не спрашивать",
shareFeedback: "Поделиться отзывом",
remindLater: "Напомнить позже",
adminCardTitle: "Как прошла установка?",
adminCardDescription:
"A quick note from admins helps us improve Docker, source installs, and docs.",
installMethodLabel: "Install method",
frictionAreaLabel: "Hardest setup area",
importantAreasLabel: "Most important areas",
"Пара слов от администраторов помогает нам улучшать Docker, установку из исходников и документацию.",
installMethodLabel: "Способ установки",
frictionAreaLabel: "Самая сложная часть установки",
importantAreasLabel: "Самые важные направления",
sentiments: {
great: "Great",
okay: "Okay",
issue: "Had an issue",
missing: "Missing something",
bug: "Bug",
idea: "Idea",
other: "Other",
great: "Отлично",
okay: "Нормально",
issue: "Была проблема",
missing: "Чего-то не хватает",
bug: "Ошибка",
idea: "Идея",
other: "Другое",
},
types: {
bug: "Bug",
feature_request: "Feature request",
confusing_ux: "Confusing UX",
performance: "Performance",
other: "Other",
bug: "Ошибка",
feature_request: "Запрос функции",
confusing_ux: "Непонятный интерфейс",
performance: "Производительность",
other: "Другое",
},
installMethods: {
docker: "Docker",
docker_compose: "Docker Compose",
source: "Built from source",
cloud: "Cloud/demo",
other: "Other",
source: "Сборка из исходников",
cloud: "Облако/демо",
other: "Другое",
},
usageTypes: {
personal: "Только я",
team_internal: "Небольшая команда",
business_workflow: "Компания или организация",
education: "Education",
evaluating: "Evaluating",
education: "Образование",
evaluating: "Ознакомление",
},
frictionAreas: {
smooth: "Nothing, setup was smooth",
docker: "Docker/container setup",
environment_variables: "Environment variables",
auth: "Authentication/SSO",
storage: "Storage/uploads",
workers: "Workers/queues",
ai_tools: "AI tools",
docs: "Documentation",
performance: "Performance/resources",
other: "Other",
smooth: "Ничего, установка прошла гладко",
docker: "Настройка Docker/контейнеров",
environment_variables: "Переменные окружения",
auth: "Аутентификация/SSO",
storage: "Хранилище/загрузки",
workers: "Воркеры/очереди",
ai_tools: "AI-инструменты",
docs: "Документация",
performance: "Производительность/ресурсы",
other: "Другое",
},
importantAreas: {
images: "Images",
pdf_docs: "PDF/docs",
video_audio: "Video/audio",
batch_workflows: "Batch workflows",
ai_tools: "AI tools",
images: "Изображения",
pdf_docs: "PDF/документы",
video_audio: "Видео/аудио",
batch_workflows: "Пакетная обработка",
ai_tools: "AI-инструменты",
},
},
onboarding: {