Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/app/src/context/language.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type Locale =
| "ja"
| "pl"
| "ru"
| "uk"
| "ar"
| "no"
| "br"
Expand Down Expand Up @@ -45,6 +46,7 @@ const LOCALES: readonly Locale[] = [
"ja",
"pl",
"ru",
"uk",
"bs",
"ar",
"no",
Expand All @@ -65,6 +67,7 @@ const INTL: Record<Locale, string> = {
ja: "ja",
pl: "pl",
ru: "ru",
uk: "uk",
ar: "ar",
no: "nb-NO",
br: "pt-BR",
Expand All @@ -85,6 +88,7 @@ const LABEL_KEY: Record<Locale, keyof Dictionary> = {
ja: "language.ja",
pl: "language.pl",
ru: "language.ru",
uk: "language.uk",
ar: "language.ar",
no: "language.no",
br: "language.br",
Expand All @@ -110,6 +114,7 @@ const loaders: Record<Exclude<Locale, "en">, () => Promise<Dictionary>> = {
ja: () => merge(import("@/i18n/ja"), import("@opencode-ai/ui/i18n/ja")),
pl: () => merge(import("@/i18n/pl"), import("@opencode-ai/ui/i18n/pl")),
ru: () => merge(import("@/i18n/ru"), import("@opencode-ai/ui/i18n/ru")),
uk: () => merge(import("@/i18n/uk"), import("@opencode-ai/ui/i18n/uk")),
ar: () => merge(import("@/i18n/ar"), import("@opencode-ai/ui/i18n/ar")),
no: () => merge(import("@/i18n/no"), import("@opencode-ai/ui/i18n/no")),
br: () => merge(import("@/i18n/br"), import("@opencode-ai/ui/i18n/br")),
Expand Down Expand Up @@ -145,6 +150,7 @@ const localeMatchers: Array<{ locale: Locale; match: (language: string) => boole
{ locale: "ja", match: (language) => language.startsWith("ja") },
{ locale: "pl", match: (language) => language.startsWith("pl") },
{ locale: "ru", match: (language) => language.startsWith("ru") },
{ locale: "uk", match: (language) => language.startsWith("uk") },
{ locale: "ar", match: (language) => language.startsWith("ar") },
{
locale: "no",
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ export const dict = {
"language.no": "Norsk",
"language.br": "Português (Brasil)",
"language.bs": "Bosanski",
"language.uk": "Українська",
"language.th": "ไทย",
"language.tr": "Türkçe",

Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/i18n/parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import { dict as ko } from "./ko"
import { dict as no } from "./no"
import { dict as pl } from "./pl"
import { dict as ru } from "./ru"
import { dict as uk } from "./uk"
import { dict as th } from "./th"
import { dict as zh } from "./zh"
import { dict as zht } from "./zht"
import { dict as tr } from "./tr"

const locales = [ar, br, bs, da, de, es, fr, ja, ko, no, pl, ru, th, tr, zh, zht]
const locales = [ar, br, bs, da, de, es, fr, ja, ko, no, pl, ru, uk, th, tr, zh, zht]
const keys = ["command.session.previous.unseen", "command.session.next.unseen"] as const

describe("i18n parity", () => {
Expand Down
963 changes: 963 additions & 0 deletions packages/app/src/i18n/uk.ts

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/console/app/src/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { dict as da } from "~/i18n/da"
import { dict as ja } from "~/i18n/ja"
import { dict as pl } from "~/i18n/pl"
import { dict as ru } from "~/i18n/ru"
import { dict as uk } from "~/i18n/uk"
import { dict as ar } from "~/i18n/ar"
import { dict as no } from "~/i18n/no"
import { dict as br } from "~/i18n/br"
Expand All @@ -35,6 +36,7 @@ export function i18n(locale: Locale): Dict {
if (locale === "ja") return { ...base, ...ja }
if (locale === "pl") return { ...base, ...pl }
if (locale === "ru") return { ...base, ...ru }
if (locale === "uk") return { ...base, ...uk }
if (locale === "ar") return { ...base, ...ar }
if (locale === "no") return { ...base, ...no }
if (locale === "br") return { ...base, ...br }
Expand Down
785 changes: 785 additions & 0 deletions packages/console/app/src/i18n/uk.ts

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions packages/console/app/src/lib/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const LOCALES = [
"ja",
"pl",
"ru",
"uk",
"ar",
"no",
"br",
Expand Down Expand Up @@ -41,6 +42,7 @@ const LABEL = {
ja: "日本語",
pl: "Polski",
ru: "Русский",
uk: "Українська",
ar: "العربية",
no: "Norsk",
br: "Português (Brasil)",
Expand All @@ -61,6 +63,7 @@ const TAG = {
ja: "ja",
pl: "pl",
ru: "ru",
uk: "uk",
ar: "ar",
no: "no",
br: "pt-BR",
Expand All @@ -81,6 +84,7 @@ const DOCS = {
ja: "ja",
pl: "pl",
ru: "ru",
uk: "uk",
ar: "ar",
no: "nb",
br: "pt-br",
Expand All @@ -104,6 +108,7 @@ const DOCS_SEGMENT = new Set([
"ru",
"th",
"tr",
"uk",
"zh-cn",
"zh-tw",
])
Expand All @@ -124,6 +129,7 @@ const DOCS_LOCALE = {
ru: "ru",
th: "th",
tr: "tr",
uk: "uk",
"zh-cn": "zh",
"zh-tw": "zht",
} as const satisfies Record<string, Locale>
Expand Down Expand Up @@ -239,6 +245,7 @@ function match(input: string): Locale | null {
if (value.startsWith("ja")) return "ja"
if (value.startsWith("pl")) return "pl"
if (value.startsWith("ru")) return "ru"
if (value.startsWith("uk")) return "uk"
if (value.startsWith("ar")) return "ar"
if (value.startsWith("tr")) return "tr"
if (value.startsWith("th")) return "th"
Expand Down
6 changes: 6 additions & 0 deletions packages/desktop/src/renderer/i18n/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { dict as desktopDa } from "./da"
import { dict as desktopJa } from "./ja"
import { dict as desktopPl } from "./pl"
import { dict as desktopRu } from "./ru"
import { dict as desktopUk } from "./uk"
import { dict as desktopAr } from "./ar"
import { dict as desktopNo } from "./no"
import { dict as desktopBr } from "./br"
Expand All @@ -27,6 +28,7 @@ import { dict as appDa } from "../../../../app/src/i18n/da"
import { dict as appJa } from "../../../../app/src/i18n/ja"
import { dict as appPl } from "../../../../app/src/i18n/pl"
import { dict as appRu } from "../../../../app/src/i18n/ru"
import { dict as appUk } from "../../../../app/src/i18n/uk"
import { dict as appAr } from "../../../../app/src/i18n/ar"
import { dict as appNo } from "../../../../app/src/i18n/no"
import { dict as appBr } from "../../../../app/src/i18n/br"
Expand All @@ -44,6 +46,7 @@ export type Locale =
| "ja"
| "pl"
| "ru"
| "uk"
| "ar"
| "no"
| "br"
Expand All @@ -64,6 +67,7 @@ const LOCALES: readonly Locale[] = [
"ja",
"pl",
"ru",
"uk",
"bs",
"ar",
"no",
Expand All @@ -89,6 +93,7 @@ function detectLocale(): Locale {
if (language.toLowerCase().startsWith("ja")) return "ja"
if (language.toLowerCase().startsWith("pl")) return "pl"
if (language.toLowerCase().startsWith("ru")) return "ru"
if (language.toLowerCase().startsWith("uk")) return "uk"
if (language.toLowerCase().startsWith("ar")) return "ar"
if (
language.toLowerCase().startsWith("no") ||
Expand Down Expand Up @@ -148,6 +153,7 @@ function build(locale: Locale): Dictionary {
if (locale === "ja") return { ...base, ...i18n.flatten(appJa), ...i18n.flatten(desktopJa) }
if (locale === "pl") return { ...base, ...i18n.flatten(appPl), ...i18n.flatten(desktopPl) }
if (locale === "ru") return { ...base, ...i18n.flatten(appRu), ...i18n.flatten(desktopRu) }
if (locale === "uk") return { ...base, ...i18n.flatten(appUk), ...i18n.flatten(desktopUk) }
if (locale === "ar") return { ...base, ...i18n.flatten(appAr), ...i18n.flatten(desktopAr) }
if (locale === "no") return { ...base, ...i18n.flatten(appNo), ...i18n.flatten(desktopNo) }
if (locale === "br") return { ...base, ...i18n.flatten(appBr), ...i18n.flatten(desktopBr) }
Expand Down
28 changes: 28 additions & 0 deletions packages/desktop/src/renderer/i18n/uk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const dict = {
"desktop.menu.checkForUpdates": "Перевірити оновлення...",
"desktop.menu.installCli": "Встановити CLI...",
"desktop.menu.reloadWebview": "Перезавантажити Webview",
"desktop.menu.restart": "Перезапустити",

"desktop.dialog.chooseFolder": "Виберіть теку",
"desktop.dialog.chooseFile": "Виберіть файл",
"desktop.dialog.saveFile": "Зберегти файл",

"desktop.updater.checkFailed.title": "Не вдалося перевірити оновлення",
"desktop.updater.checkFailed.message": "Не вдалося перевірити наявність оновлень",
"desktop.updater.none.title": "Немає доступних оновлень",
"desktop.updater.none.message": "Ви вже використовуєте найновішу версію OpenCode",
"desktop.updater.downloadFailed.title": "Помилка оновлення",
"desktop.updater.downloadFailed.message": "Не вдалося завантажити оновлення",
"desktop.updater.downloaded.title": "Оновлення завантажено",
"desktop.updater.downloaded.prompt":
"Версію {{version}} OpenCode завантажено. Бажаєте встановити її та перезапустити?",
"desktop.updater.installFailed.title": "Помилка оновлення",
"desktop.updater.installFailed.message": "Не вдалося встановити оновлення",

"desktop.cli.installed.title": "CLI встановлено",
"desktop.cli.installed.message":
"CLI встановлено до {{path}}\n\nПерезапустіть термінал, щоб використовувати команду 'opencode'.",
"desktop.cli.failed.title": "Не вдалося встановити",
"desktop.cli.failed.message": "Не вдалося встановити CLI: {{error}}",
}
167 changes: 167 additions & 0 deletions packages/ui/src/i18n/uk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
export const dict: Record<string, string> = {
"ui.sessionReview.title": "Зміни сесії",
"ui.sessionReview.title.git": "Зміни Git",
"ui.sessionReview.title.branch": "Зміни гілки",
"ui.sessionReview.title.lastTurn": "Зміни останнього кроку",
"ui.sessionReview.diffStyle.unified": "Об'єднаний",
"ui.sessionReview.diffStyle.split": "Розділений",
"ui.sessionReview.expandAll": "Розгорнути все",
"ui.sessionReview.collapseAll": "Згорнути все",
"ui.sessionReview.change.added": "Додано",
"ui.sessionReview.change.removed": "Видалено",
"ui.sessionReview.change.modified": "Змінено",
"ui.sessionReview.image.loading": "Завантаження...",
"ui.sessionReview.image.placeholder": "Зображення",
"ui.sessionReview.largeDiff.title": "Завеликий diff для відображення",
"ui.sessionReview.largeDiff.meta": "Ліміт: {{limit}} змінених рядків. Поточно: {{current}} змінених рядків.",
"ui.sessionReview.largeDiff.renderAnyway": "Все одно відобразити",
"ui.sessionReview.openFile": "Відкрити файл",
"ui.sessionReview.selection.line": "рядок {{line}}",
"ui.sessionReview.selection.lines": "рядки {{start}}-{{end}}",

"ui.fileMedia.kind.image": "зображення",
"ui.fileMedia.kind.audio": "аудіо",
"ui.fileMedia.state.removed": "{{kind}} видалено",
"ui.fileMedia.state.loading": "Завантаження {{kind}}...",
"ui.fileMedia.state.error": "Не вдалося завантажити {{kind}}",
"ui.fileMedia.state.unavailable": "{{kind}} недоступне",
"ui.fileMedia.binary.title": "Бінарний файл",
"ui.fileMedia.binary.description.path": "Неможливо відобразити {{path}}, оскільки це бінарний файл.",
"ui.fileMedia.binary.description.default": "Неможливо відобразити цей файл, оскільки він бінарний.",

"ui.lineComment.label.prefix": "Коментар до ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Коментування: ",
"ui.lineComment.editorLabel.suffix": "",
"ui.lineComment.placeholder": "Додати коментар",
"ui.lineComment.submit": "Коментувати",

"ui.sessionTurn.steps.show": "Показати кроки",
"ui.sessionTurn.steps.hide": "Приховати кроки",
"ui.sessionTurn.summary.response": "Відповідь",
"ui.sessionTurn.diff.showMore": "Показати більше змін ({{count}})",
"ui.sessionTurn.diffs.changed": "Змінено",
"ui.sessionTurn.diffs.showAll": "Показати всі",
"ui.sessionTurn.diffs.showLess": "Показати менше",
"ui.sessionTurn.diffs.more": "+{{count}} інших файлів",

"ui.sessionTurn.retry.retrying": "повтор",
"ui.sessionTurn.retry.inSeconds": "за {{seconds}}с",
"ui.sessionTurn.retry.attempt": "спроба №{{attempt}}",
"ui.sessionTurn.retry.attemptLine": "{{line}} — спроба №{{attempt}}",
"ui.sessionTurn.retry.geminiHot": "gemini зараз перевантажений",
"ui.sessionTurn.error.freeUsageExceeded": "Перевищено ліміт безкоштовного використання",
"ui.sessionTurn.error.addCredits": "Додати кредити",

"ui.sessionTurn.status.delegating": "Делегування роботи",
"ui.sessionTurn.status.planning": "Планування наступних кроків",
"ui.sessionTurn.status.gatheringContext": "Дослідження",
"ui.sessionTurn.status.gatheredContext": "Досліджено",
"ui.sessionTurn.status.searchingCodebase": "Пошук у кодовій базі",
"ui.sessionTurn.status.searchingWeb": "Пошук в інтернеті",
"ui.sessionTurn.status.makingEdits": "Внесення змін",
"ui.sessionTurn.status.runningCommands": "Виконання команд",
"ui.sessionTurn.status.thinking": "Міркування",
"ui.sessionTurn.status.thinkingWithTopic": "Міркування — {{topic}}",
"ui.sessionTurn.status.gatheringThoughts": "Збирання думок",
"ui.sessionTurn.status.consideringNextSteps": "Розгляд наступних кроків",

"ui.messagePart.diagnostic.error": "Помилка",
"ui.messagePart.title.edit": "Редагувати",
"ui.messagePart.title.write": "Написати",
"ui.messagePart.option.typeOwnAnswer": "Введіть власну відповідь",
"ui.messagePart.review.title": "Перевірте свої відповіді",
"ui.messagePart.questions.dismissed": "Питання відхилено",
"ui.messagePart.compaction": "Сесію стиснуто",
"ui.messagePart.context.read.one": "{{count}} читання",
"ui.messagePart.context.read.other": "{{count}} читань",
"ui.messagePart.context.search.one": "{{count}} пошук",
"ui.messagePart.context.search.other": "{{count}} пошуків",
"ui.messagePart.context.list.one": "{{count}} список",
"ui.messagePart.context.list.other": "{{count}} списків",

"ui.list.loading": "Завантаження",
"ui.list.empty": "Немає результатів",
"ui.list.clearFilter": "Очистити фільтр",
"ui.list.emptyWithFilter.prefix": "Немає результатів для",
"ui.list.emptyWithFilter.suffix": "",

"ui.fileSearch.placeholder": "Знайти",
"ui.fileSearch.previousMatch": "Попередній збіг",
"ui.fileSearch.nextMatch": "Наступний збіг",
"ui.fileSearch.close": "Закрити пошук",

"ui.messageNav.newMessage": "Нове повідомлення",

"ui.textField.copyToClipboard": "Копіювати в буфер обміну",
"ui.textField.copyLink": "Копіювати посилання",
"ui.textField.copied": "Скопійовано",

"ui.imagePreview.alt": "Попередній перегляд зображення",
"ui.scrollView.ariaLabel": "контент для прокручування",

"ui.tool.read": "Читання",
"ui.tool.loaded": "Завантажено",
"ui.tool.list": "Список",
"ui.tool.glob": "Glob",
"ui.tool.grep": "Grep",
"ui.tool.task": "Завдання",
"ui.tool.webfetch": "Веб-отримання",
"ui.tool.websearch": "Веб-пошук",
"ui.tool.shell": "Оболонка",
"ui.tool.patch": "Патч",
"ui.tool.todos": "Завдання",
"ui.tool.todos.read": "Читати завдання",
"ui.tool.questions": "Питання",
"ui.tool.agent": "Агент {{type}}",
"ui.tool.agent.default": "Агент",
"ui.tool.skill": "Навичка",

"ui.basicTool.called": "Викликано `{{tool}}`",
"ui.toolErrorCard.failed": "Помилка",
"ui.toolErrorCard.copyError": "Копіювати помилку",

"ui.common.file.one": "файл",
"ui.common.file.other": "файлів",
"ui.common.question.one": "питання",
"ui.common.question.other": "питань",

"ui.common.add": "Додати",
"ui.common.back": "Назад",
"ui.common.cancel": "Скасувати",
"ui.common.confirm": "Підтвердити",
"ui.common.dismiss": "Відхилити",
"ui.common.close": "Закрити",
"ui.common.next": "Далі",
"ui.common.submit": "Надіслати",

"ui.permission.deny": "Заборонити",
"ui.permission.allowAlways": "Дозволяти завжди",
"ui.permission.allowOnce": "Дозволити один раз",

"ui.message.expand": "Розгорнути повідомлення",
"ui.message.collapse": "Згорнути повідомлення",
"ui.message.copy": "Копіювати",
"ui.message.copyMessage": "Копіювати повідомлення",
"ui.message.forkMessage": "Відгалузити в нову сесію",
"ui.message.revertMessage": "Скинути до цього моменту",
"ui.message.copyResponse": "Копіювати відповідь",
"ui.message.copied": "Скопійовано",
"ui.message.duration.seconds": "{{count}}с",
"ui.message.duration.minutesSeconds": "{{minutes}}хв {{seconds}}с",
"ui.message.interrupted": "Перервано",
"ui.message.queued": "У черзі",
"ui.message.attachment.alt": "вкладення",

"ui.patch.action.deleted": "Видалено",
"ui.patch.action.created": "Створено",
"ui.patch.action.moved": "Переміщено",
"ui.patch.action.patched": "Пропатчено",

"ui.question.subtitle.answered": "{{count}} відповідей",
"ui.question.answer.none": "(немає відповіді)",
"ui.question.review.notAnswered": "(не відповіли)",
"ui.question.multiHint": "Виберіть усі відповідні варіанти",
"ui.question.singleHint": "Виберіть одну відповідь",
"ui.question.custom.placeholder": "Введіть свою відповідь...",
}
Loading
Loading