feat: init
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
chuan
2025-11-11 01:56:44 +08:00
commit bba4bb40c8
4638 changed files with 447437 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
build/*
dist/*
out/*

View File

@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: ["@plane/eslint-config/library.js"],
};

View File

@@ -0,0 +1,7 @@
.turbo
out/
dist/
build/
.next
.vercel
.turbo

View File

@@ -0,0 +1,5 @@
{
"printWidth": 120,
"tabWidth": 2,
"trailingComma": "es5"
}

View File

@@ -0,0 +1,44 @@
{
"name": "@plane/i18n",
"version": "1.1.0",
"license": "AGPL-3.0",
"description": "I18n shared across multiple apps internally",
"private": true,
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./package.json": "./package.json"
},
"scripts": {
"dev": "tsdown --watch",
"build": "tsdown",
"check:lint": "eslint . --max-warnings 2",
"check:types": "tsc --noEmit",
"check:format": "prettier --check \"**/*.{ts,tsx,md,json,css,scss}\"",
"fix:lint": "eslint . --fix",
"fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"",
"clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist"
},
"dependencies": {
"@plane/utils": "workspace:*",
"intl-messageformat": "^10.7.11",
"mobx": "catalog:",
"mobx-react": "catalog:",
"lodash-es": "catalog:",
"react": "catalog:"
},
"devDependencies": {
"@plane/eslint-config": "workspace:*",
"@plane/typescript-config": "workspace:*",
"@types/node": "catalog:",
"@types/lodash-es": "catalog:",
"@types/react": "catalog:",
"tsdown": "catalog:",
"typescript": "catalog:"
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts"
}

View File

@@ -0,0 +1 @@
export * from "./language";

View File

@@ -0,0 +1,37 @@
import { TLanguage, ILanguageOption } from "../types";
export const FALLBACK_LANGUAGE: TLanguage = "en";
export const SUPPORTED_LANGUAGES: ILanguageOption[] = [
{ label: "English", value: "en" },
{ label: "Français", value: "fr" },
{ label: "Español", value: "es" },
{ label: "日本語", value: "ja" },
{ label: "简体中文", value: "zh-CN" },
{ label: "繁體中文", value: "zh-TW" },
{ label: "Русский", value: "ru" },
{ label: "Italian", value: "it" },
{ label: "Čeština", value: "cs" },
{ label: "Slovenčina", value: "sk" },
{ label: "Deutsch", value: "de" },
{ label: "Українська", value: "ua" },
{ label: "Polski", value: "pl" },
{ label: "한국어", value: "ko" },
{ label: "Português Brasil", value: "pt-BR" },
{ label: "Indonesian", value: "id" },
{ label: "Română", value: "ro" },
{ label: "Tiếng việt", value: "vi-VN" },
{ label: "Türkçe", value: "tr-TR" },
];
/**
* Enum for translation file names
* These are the JSON files that contain translations each category
*/
export enum ETranslationFiles {
TRANSLATIONS = "translations",
ACCESSIBILITY = "accessibility",
EDITOR = "editor",
}
export const LANGUAGE_STORAGE_KEY = "userLanguage";

View File

@@ -0,0 +1,19 @@
import { observer } from "mobx-react";
import React, { createContext } from "react";
// store
import { TranslationStore } from "../store";
export const TranslationContext = createContext<TranslationStore | null>(null);
interface TranslationProviderProps {
children: React.ReactNode;
}
/**
* Provides the translation store to the application
*/
export const TranslationProvider: React.FC<TranslationProviderProps> = observer(({ children }) => {
const [store] = React.useState(() => new TranslationStore());
return <TranslationContext.Provider value={store}>{children}</TranslationContext.Provider>;
});

View File

@@ -0,0 +1 @@
export * from "./use-translation";

View File

@@ -0,0 +1,35 @@
import { useContext } from "react";
// context
import { TranslationContext } from "../context";
// types
import { ILanguageOption, TLanguage } from "../types";
export type TTranslationStore = {
t: (key: string, params?: Record<string, unknown>) => string;
currentLocale: TLanguage;
changeLanguage: (lng: TLanguage) => void;
languages: ILanguageOption[];
};
/**
* Provides the translation store to the application
* @returns {TTranslationStore}
* @returns {(key: string, params?: Record<string, any>) => string} t: method to translate the key with params
* @returns {TLanguage} currentLocale - current locale language
* @returns {(lng: TLanguage) => void} changeLanguage - method to change the language
* @returns {ILanguageOption[]} languages - available languages
* @throws {Error} if the TranslationProvider is not used
*/
export function useTranslation(): TTranslationStore {
const store = useContext(TranslationContext);
if (!store) {
throw new Error("useTranslation must be used within a TranslationProvider");
}
return {
t: store.t.bind(store),
currentLocale: store.currentLocale,
changeLanguage: (lng: TLanguage) => store.setLanguage(lng),
languages: store.availableLanguages,
};
}

View File

@@ -0,0 +1,6 @@
export * from "./constants";
export * from "./context";
export * from "./hooks";
export * from "./types";
export * from "./store";
export * from "./locales";

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo pracovního prostoru",
open_workspace_switcher: "Otevřít přepínač pracovního prostoru",
open_user_menu: "Otevřít uživatelské menu",
open_command_palette: "Otevřít paletu příkazů",
open_extended_sidebar: "Otevřít rozšířený postranní panel",
close_extended_sidebar: "Zavřít rozšířený postranní panel",
create_favorites_folder: "Vytvořit složku oblíbených",
open_folder: "Otevřít složku",
close_folder: "Zavřít složku",
open_favorites_menu: "Otevřít menu oblíbených",
close_favorites_menu: "Zavřít menu oblíbených",
enter_folder_name: "Zadejte název složky",
create_new_project: "Vytvořit nový projekt",
open_projects_menu: "Otevřít menu projektů",
close_projects_menu: "Zavřít menu projektů",
toggle_quick_actions_menu: "Přepnout menu rychlých akcí",
open_project_menu: "Otevřít menu projektu",
close_project_menu: "Zavřít menu projektu",
collapse_sidebar: "Sbalit postranní panel",
expand_sidebar: "Rozbalit postranní panel",
edition_badge: "Otevřít modal placených plánů",
},
auth_forms: {
clear_email: "Vymazat e-mail",
show_password: "Zobrazit heslo",
hide_password: "Skrýt heslo",
close_alert: "Zavřít upozornění",
close_popover: "Zavřít vyskakovací okno",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Arbeitsbereich-Logo",
open_workspace_switcher: "Arbeitsbereich-Umschalter öffnen",
open_user_menu: "Benutzermenü öffnen",
open_command_palette: "Befehlspalette öffnen",
open_extended_sidebar: "Erweiterte Seitenleiste öffnen",
close_extended_sidebar: "Erweiterte Seitenleiste schließen",
create_favorites_folder: "Favoriten-Ordner erstellen",
open_folder: "Ordner öffnen",
close_folder: "Ordner schließen",
open_favorites_menu: "Favoriten-Menü öffnen",
close_favorites_menu: "Favoriten-Menü schließen",
enter_folder_name: "Ordnername eingeben",
create_new_project: "Neues Projekt erstellen",
open_projects_menu: "Projekt-Menü öffnen",
close_projects_menu: "Projekt-Menü schließen",
toggle_quick_actions_menu: "Schnellaktionen-Menü umschalten",
open_project_menu: "Projekt-Menü öffnen",
close_project_menu: "Projekt-Menü schließen",
collapse_sidebar: "Seitenleiste einklappen",
expand_sidebar: "Seitenleiste ausklappen",
edition_badge: "Modal für kostenpflichtige Pläne öffnen",
},
auth_forms: {
clear_email: "E-Mail löschen",
show_password: "Passwort anzeigen",
hide_password: "Passwort verbergen",
close_alert: "Warnung schließen",
close_popover: "Popover schließen",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Workspace logo",
open_workspace_switcher: "Open workspace switcher",
open_user_menu: "Open user menu",
open_command_palette: "Open command palette",
open_extended_sidebar: "Open extended sidebar",
close_extended_sidebar: "Close extended sidebar",
create_favorites_folder: "Create favorites folder",
open_folder: "Open folder",
close_folder: "Close folder",
open_favorites_menu: "Open favorites menu",
close_favorites_menu: "Close favorites menu",
enter_folder_name: "Enter folder name",
create_new_project: "Create new project",
open_projects_menu: "Open projects menu",
close_projects_menu: "Close projects menu",
toggle_quick_actions_menu: "Toggle quick actions menu",
open_project_menu: "Open project menu",
close_project_menu: "Close project menu",
collapse_sidebar: "Collapse sidebar",
expand_sidebar: "Expand sidebar",
edition_badge: "Open paid plans' modal",
},
auth_forms: {
clear_email: "Clear email",
show_password: "Show password",
hide_password: "Hide password",
close_alert: "Close alert",
close_popover: "Close popover",
},
},
} as const;

View File

@@ -0,0 +1,172 @@
export default {
sidebar: {
projects: "Projects",
pages: "Pages",
new_work_item: "New work item",
home: "Home",
your_work: "Your work",
inbox: "Inbox",
workspace: "Workspace",
views: "Views",
analytics: "Analytics",
work_items: "Work items",
cycles: "Cycles",
modules: "Modules",
intake: "Intake",
drafts: "Drafts",
favorites: "Favorites",
pro: "Pro",
upgrade: "Upgrade",
},
auth: {
common: {
email: {
label: "Email",
placeholder: "name@company.com",
errors: {
required: "Email is required",
invalid: "Email is invalid",
},
},
password: {
label: "Password",
set_password: "Set a password",
placeholder: "Enter password",
confirm_password: {
label: "Confirm password",
placeholder: "Confirm password",
},
current_password: {
label: "Current password",
},
new_password: {
label: "New password",
placeholder: "Enter new password",
},
change_password: {
label: {
default: "Change password",
submitting: "Changing password",
},
},
errors: {
match: "Passwords don't match",
empty: "Please enter your password",
length: "Password length should me more than 8 characters",
strength: {
weak: "Password is weak",
strong: "Password is strong",
},
},
submit: "Set password",
toast: {
change_password: {
success: {
title: "Success!",
message: "Password changed successfully.",
},
error: {
title: "Error!",
message: "Something went wrong. Please try again.",
},
},
},
},
unique_code: {
label: "Unique code",
placeholder: "gets-sets-flys",
paste_code: "Paste the code sent to your email",
requesting_new_code: "Requesting new code",
sending_code: "Sending code",
},
already_have_an_account: "Already have an account?",
login: "Log in",
create_account: "Create an account",
new_to_plane: "New to Plane?",
back_to_sign_in: "Back to sign in",
resend_in: "Resend in {seconds} seconds",
sign_in_with_unique_code: "Sign in with unique code",
forgot_password: "Forgot your password?",
},
sign_up: {
header: {
label: "Create an account to start managing work with your team.",
step: {
email: {
header: "Sign up",
sub_header: "",
},
password: {
header: "Sign up",
sub_header: "Sign up using an email-password combination.",
},
unique_code: {
header: "Sign up",
sub_header: "Sign up using a unique code sent to the email address above.",
},
},
},
errors: {
password: {
strength: "Try setting-up a strong password to proceed",
},
},
},
sign_in: {
header: {
label: "Log in to start managing work with your team.",
step: {
email: {
header: "Log in or sign up",
sub_header: "",
},
password: {
header: "Log in or sign up",
sub_header: "Use your email-password combination to log in.",
},
unique_code: {
header: "Log in or sign up",
sub_header: "Log in using a unique code sent to the email address above.",
},
},
},
},
forgot_password: {
title: "Reset your password",
description: "Enter your user account's verified email address and we will send you a password reset link.",
email_sent: "We sent the reset link to your email address",
send_reset_link: "Send reset link",
errors: {
smtp_not_enabled: "We see that your god hasn't enabled SMTP, we will not be able to send a password reset link",
},
toast: {
success: {
title: "Email sent",
message:
"Check your inbox for a link to reset your password. If it doesn't appear within a few minutes, check your spam folder.",
},
error: {
title: "Error!",
message: "Something went wrong. Please try again.",
},
},
},
reset_password: {
title: "Set new password",
description: "Secure your account with a strong password",
},
set_password: {
title: "Secure your account",
description: "Setting password helps you login securely",
},
sign_out: {
toast: {
error: {
title: "Error!",
message: "Failed to sign out. Please try again.",
},
},
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo del espacio de trabajo",
open_workspace_switcher: "Abrir cambiador de espacio de trabajo",
open_user_menu: "Abrir menú de usuario",
open_command_palette: "Abrir paleta de comandos",
open_extended_sidebar: "Abrir barra lateral extendida",
close_extended_sidebar: "Cerrar barra lateral extendida",
create_favorites_folder: "Crear carpeta de favoritos",
open_folder: "Abrir carpeta",
close_folder: "Cerrar carpeta",
open_favorites_menu: "Abrir menú de favoritos",
close_favorites_menu: "Cerrar menú de favoritos",
enter_folder_name: "Ingresar nombre de carpeta",
create_new_project: "Crear nuevo proyecto",
open_projects_menu: "Abrir menú de proyectos",
close_projects_menu: "Cerrar menú de proyectos",
toggle_quick_actions_menu: "Alternar menú de acciones rápidas",
open_project_menu: "Abrir menú de proyecto",
close_project_menu: "Cerrar menú de proyecto",
collapse_sidebar: "Colapsar barra lateral",
expand_sidebar: "Expandir barra lateral",
edition_badge: "Abrir modal de planes de pago",
},
auth_forms: {
clear_email: "Limpiar correo electrónico",
show_password: "Mostrar contraseña",
hide_password: "Ocultar contraseña",
close_alert: "Cerrar alerta",
close_popover: "Cerrar ventana emergente",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo de l'espace de travail",
open_workspace_switcher: "Ouvrir le sélecteur d'espace de travail",
open_user_menu: "Ouvrir le menu utilisateur",
open_command_palette: "Ouvrir la palette de commandes",
open_extended_sidebar: "Ouvrir la barre latérale étendue",
close_extended_sidebar: "Fermer la barre latérale étendue",
create_favorites_folder: "Créer un dossier de favoris",
open_folder: "Ouvrir le dossier",
close_folder: "Fermer le dossier",
open_favorites_menu: "Ouvrir le menu des favoris",
close_favorites_menu: "Fermer le menu des favoris",
enter_folder_name: "Saisir le nom du dossier",
create_new_project: "Créer un nouveau projet",
open_projects_menu: "Ouvrir le menu des projets",
close_projects_menu: "Fermer le menu des projets",
toggle_quick_actions_menu: "Basculer le menu d'actions rapides",
open_project_menu: "Ouvrir le menu du projet",
close_project_menu: "Fermer le menu du projet",
collapse_sidebar: "Réduire la barre latérale",
expand_sidebar: "Étendre la barre latérale",
edition_badge: "Ouvrir le modal des plans payants",
},
auth_forms: {
clear_email: "Effacer l'e-mail",
show_password: "Afficher le mot de passe",
hide_password: "Masquer le mot de passe",
close_alert: "Fermer l'alerte",
close_popover: "Fermer la fenêtre contextuelle",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo ruang kerja",
open_workspace_switcher: "Buka penukar ruang kerja",
open_user_menu: "Buka menu pengguna",
open_command_palette: "Buka palet perintah",
open_extended_sidebar: "Buka sidebar diperluas",
close_extended_sidebar: "Tutup sidebar diperluas",
create_favorites_folder: "Buat folder favorit",
open_folder: "Buka folder",
close_folder: "Tutup folder",
open_favorites_menu: "Buka menu favorit",
close_favorites_menu: "Tutup menu favorit",
enter_folder_name: "Masukkan nama folder",
create_new_project: "Buat proyek baru",
open_projects_menu: "Buka menu proyek",
close_projects_menu: "Tutup menu proyek",
toggle_quick_actions_menu: "Alihkan menu tindakan cepat",
open_project_menu: "Buka menu proyek",
close_project_menu: "Tutup menu proyek",
collapse_sidebar: "Tutup sidebar",
expand_sidebar: "Perluas sidebar",
edition_badge: "Buka modal paket berbayar",
},
auth_forms: {
clear_email: "Hapus email",
show_password: "Tampilkan kata sandi",
hide_password: "Sembunyikan kata sandi",
close_alert: "Tutup peringatan",
close_popover: "Tutup popover",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,105 @@
// Export all locale files to make them accessible from the package root
export { default as enCore } from "./en/core";
export { default as enTranslations } from "./en/translations";
export { default as enAccessibility } from "./en/accessibility";
export { default as enEditor } from "./en/editor";
// Export locale data for all supported languages
export const locales = {
en: {
core: () => import("./en/core"),
translations: () => import("./en/translations"),
accessibility: () => import("./en/accessibility"),
editor: () => import("./en/editor"),
},
fr: {
translations: () => import("./fr/translations"),
accessibility: () => import("./fr/accessibility"),
editor: () => import("./fr/editor"),
},
es: {
translations: () => import("./es/translations"),
accessibility: () => import("./es/accessibility"),
editor: () => import("./es/editor"),
},
ja: {
translations: () => import("./ja/translations"),
accessibility: () => import("./ja/accessibility"),
editor: () => import("./ja/editor"),
},
"zh-CN": {
translations: () => import("./zh-CN/translations"),
accessibility: () => import("./zh-CN/accessibility"),
editor: () => import("./zh-CN/editor"),
},
"zh-TW": {
translations: () => import("./zh-TW/translations"),
accessibility: () => import("./zh-TW/accessibility"),
editor: () => import("./zh-TW/editor"),
},
ru: {
translations: () => import("./ru/translations"),
accessibility: () => import("./ru/accessibility"),
editor: () => import("./ru/editor"),
},
it: {
translations: () => import("./it/translations"),
accessibility: () => import("./it/accessibility"),
editor: () => import("./it/editor"),
},
cs: {
translations: () => import("./cs/translations"),
accessibility: () => import("./cs/accessibility"),
editor: () => import("./cs/editor"),
},
sk: {
translations: () => import("./sk/translations"),
accessibility: () => import("./sk/accessibility"),
editor: () => import("./sk/editor"),
},
de: {
translations: () => import("./de/translations"),
accessibility: () => import("./de/accessibility"),
editor: () => import("./de/editor"),
},
ua: {
translations: () => import("./ua/translations"),
accessibility: () => import("./ua/accessibility"),
editor: () => import("./ua/editor"),
},
pl: {
translations: () => import("./pl/translations"),
accessibility: () => import("./pl/accessibility"),
editor: () => import("./pl/editor"),
},
ko: {
translations: () => import("./ko/translations"),
accessibility: () => import("./ko/accessibility"),
editor: () => import("./ko/editor"),
},
"pt-BR": {
translations: () => import("./pt-BR/translations"),
accessibility: () => import("./pt-BR/accessibility"),
editor: () => import("./pt-BR/editor"),
},
id: {
translations: () => import("./id/translations"),
accessibility: () => import("./id/accessibility"),
editor: () => import("./id/editor"),
},
ro: {
translations: () => import("./ro/translations"),
accessibility: () => import("./ro/accessibility"),
editor: () => import("./ro/editor"),
},
"vi-VN": {
translations: () => import("./vi-VN/translations"),
accessibility: () => import("./vi-VN/accessibility"),
editor: () => import("./vi-VN/editor"),
},
"tr-TR": {
translations: () => import("./tr-TR/translations"),
accessibility: () => import("./tr-TR/accessibility"),
editor: () => import("./tr-TR/editor"),
},
};

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo dell'area di lavoro",
open_workspace_switcher: "Apri selettore area di lavoro",
open_user_menu: "Apri menu utente",
open_command_palette: "Apri tavolozza comandi",
open_extended_sidebar: "Apri barra laterale estesa",
close_extended_sidebar: "Chiudi barra laterale estesa",
create_favorites_folder: "Crea cartella preferiti",
open_folder: "Apri cartella",
close_folder: "Chiudi cartella",
open_favorites_menu: "Apri menu preferiti",
close_favorites_menu: "Chiudi menu preferiti",
enter_folder_name: "Inserisci nome cartella",
create_new_project: "Crea nuovo progetto",
open_projects_menu: "Apri menu progetti",
close_projects_menu: "Chiudi menu progetti",
toggle_quick_actions_menu: "Attiva/disattiva menu azioni rapide",
open_project_menu: "Apri menu progetto",
close_project_menu: "Chiudi menu progetto",
collapse_sidebar: "Comprimi barra laterale",
expand_sidebar: "Espandi barra laterale",
edition_badge: "Apri modal piani a pagamento",
},
auth_forms: {
clear_email: "Cancella email",
show_password: "Mostra password",
hide_password: "Nascondi password",
close_alert: "Chiudi avviso",
close_popover: "Chiudi popover",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "ワークスペースロゴ",
open_workspace_switcher: "ワークスペーススイッチャーを開く",
open_user_menu: "ユーザーメニューを開く",
open_command_palette: "コマンドパレットを開く",
open_extended_sidebar: "拡張サイドバーを開く",
close_extended_sidebar: "拡張サイドバーを閉じる",
create_favorites_folder: "お気に入りフォルダを作成",
open_folder: "フォルダを開く",
close_folder: "フォルダを閉じる",
open_favorites_menu: "お気に入りメニューを開く",
close_favorites_menu: "お気に入りメニューを閉じる",
enter_folder_name: "フォルダ名を入力",
create_new_project: "新しいプロジェクトを作成",
open_projects_menu: "プロジェクトメニューを開く",
close_projects_menu: "プロジェクトメニューを閉じる",
toggle_quick_actions_menu: "クイックアクションメニューの切り替え",
open_project_menu: "プロジェクトメニューを開く",
close_project_menu: "プロジェクトメニューを閉じる",
collapse_sidebar: "サイドバーを折りたたむ",
expand_sidebar: "サイドバーを展開",
edition_badge: "有料プランのモーダルを開く",
},
auth_forms: {
clear_email: "メールをクリア",
show_password: "パスワードを表示",
hide_password: "パスワードを非表示",
close_alert: "アラートを閉じる",
close_popover: "ポップオーバーを閉じる",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "워크스페이스 로고",
open_workspace_switcher: "워크스페이스 전환기 열기",
open_user_menu: "사용자 메뉴 열기",
open_command_palette: "명령 팔레트 열기",
open_extended_sidebar: "확장된 사이드바 열기",
close_extended_sidebar: "확장된 사이드바 닫기",
create_favorites_folder: "즐겨찾기 폴더 생성",
open_folder: "폴더 열기",
close_folder: "폴더 닫기",
open_favorites_menu: "즐겨찾기 메뉴 열기",
close_favorites_menu: "즐겨찾기 메뉴 닫기",
enter_folder_name: "폴더 이름 입력",
create_new_project: "새 프로젝트 생성",
open_projects_menu: "프로젝트 메뉴 열기",
close_projects_menu: "프로젝트 메뉴 닫기",
toggle_quick_actions_menu: "빠른 작업 메뉴 토글",
open_project_menu: "프로젝트 메뉴 열기",
close_project_menu: "프로젝트 메뉴 닫기",
collapse_sidebar: "사이드바 축소",
expand_sidebar: "사이드바 확장",
edition_badge: "유료 플랜 모달 열기",
},
auth_forms: {
clear_email: "이메일 지우기",
show_password: "비밀번호 표시",
hide_password: "비밀번호 숨기기",
close_alert: "알림 닫기",
close_popover: "팝오버 닫기",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo obszaru roboczego",
open_workspace_switcher: "Otwórz przełącznik obszaru roboczego",
open_user_menu: "Otwórz menu użytkownika",
open_command_palette: "Otwórz paletę poleceń",
open_extended_sidebar: "Otwórz rozszerzoną pasek boczny",
close_extended_sidebar: "Zamknij rozszerzoną pasek boczny",
create_favorites_folder: "Utwórz folder ulubionych",
open_folder: "Otwórz folder",
close_folder: "Zamknij folder",
open_favorites_menu: "Otwórz menu ulubionych",
close_favorites_menu: "Zamknij menu ulubionych",
enter_folder_name: "Wprowadź nazwę folderu",
create_new_project: "Utwórz nowy projekt",
open_projects_menu: "Otwórz menu projektów",
close_projects_menu: "Zamknij menu projektów",
toggle_quick_actions_menu: "Przełącz menu szybkich akcji",
open_project_menu: "Otwórz menu projektu",
close_project_menu: "Zamknij menu projektu",
collapse_sidebar: "Zwiń pasek boczny",
expand_sidebar: "Rozwiń pasek boczny",
edition_badge: "Otwórz modal płatnych planów",
},
auth_forms: {
clear_email: "Wyczyść e-mail",
show_password: "Pokaż hasło",
hide_password: "Ukryj hasło",
close_alert: "Zamknij alert",
close_popover: "Zamknij popover",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo do espaço de trabalho",
open_workspace_switcher: "Abrir seletor de espaço de trabalho",
open_user_menu: "Abrir menu do usuário",
open_command_palette: "Abrir paleta de comandos",
open_extended_sidebar: "Abrir barra lateral estendida",
close_extended_sidebar: "Fechar barra lateral estendida",
create_favorites_folder: "Criar pasta de favoritos",
open_folder: "Abrir pasta",
close_folder: "Fechar pasta",
open_favorites_menu: "Abrir menu de favoritos",
close_favorites_menu: "Fechar menu de favoritos",
enter_folder_name: "Digite o nome da pasta",
create_new_project: "Criar novo projeto",
open_projects_menu: "Abrir menu de projetos",
close_projects_menu: "Fechar menu de projetos",
toggle_quick_actions_menu: "Alternar menu de ações rápidas",
open_project_menu: "Abrir menu do projeto",
close_project_menu: "Fechar menu do projeto",
collapse_sidebar: "Recolher barra lateral",
expand_sidebar: "Expandir barra lateral",
edition_badge: "Abrir modal de planos pagos",
},
auth_forms: {
clear_email: "Limpar e-mail",
show_password: "Mostrar senha",
hide_password: "Ocultar senha",
close_alert: "Fechar alerta",
close_popover: "Fechar popover",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo spațiu de lucru",
open_workspace_switcher: "Deschide comutator spațiu de lucru",
open_user_menu: "Deschide meniul utilizatorului",
open_command_palette: "Deschide paleta de comenzi",
open_extended_sidebar: "Deschide bara laterală extinsă",
close_extended_sidebar: "Închide bara laterală extinsă",
create_favorites_folder: "Creează folder de favorite",
open_folder: "Deschide folderul",
close_folder: "Închide folderul",
open_favorites_menu: "Deschide meniul de favorite",
close_favorites_menu: "Închide meniul de favorite",
enter_folder_name: "Introduceți numele folderului",
create_new_project: "Creează proiect nou",
open_projects_menu: "Deschide meniul de proiecte",
close_projects_menu: "Închide meniul de proiecte",
toggle_quick_actions_menu: "Comută meniul de acțiuni rapide",
open_project_menu: "Deschide meniul proiectului",
close_project_menu: "Închide meniul proiectului",
collapse_sidebar: "Restrânge bara laterală",
expand_sidebar: "Extinde bara laterală",
edition_badge: "Deschide modalul planurilor plătite",
},
auth_forms: {
clear_email: "Șterge e-mailul",
show_password: "Afișează parola",
hide_password: "Ascunde parola",
close_alert: "Închide alerta",
close_popover: "Închide popover-ul",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Логотип рабочей области",
open_workspace_switcher: "Открыть переключатель рабочей области",
open_user_menu: "Открыть пользовательское меню",
open_command_palette: "Открыть палитру команд",
open_extended_sidebar: "Открыть расширенную боковую панель",
close_extended_sidebar: "Закрыть расширенную боковую панель",
create_favorites_folder: "Создать папку избранного",
open_folder: "Открыть папку",
close_folder: "Закрыть папку",
open_favorites_menu: "Открыть меню избранного",
close_favorites_menu: "Закрыть меню избранного",
enter_folder_name: "Введите имя папки",
create_new_project: "Создать новый проект",
open_projects_menu: "Открыть меню проектов",
close_projects_menu: "Закрыть меню проектов",
toggle_quick_actions_menu: "Переключить меню быстрых действий",
open_project_menu: "Открыть меню проекта",
close_project_menu: "Закрыть меню проекта",
collapse_sidebar: "Свернуть боковую панель",
expand_sidebar: "Развернуть боковую панель",
edition_badge: "Открыть модал платных планов",
},
auth_forms: {
clear_email: "Очистить email",
show_password: "Показать пароль",
hide_password: "Скрыть пароль",
close_alert: "Закрыть уведомление",
close_popover: "Закрыть всплывающее окно",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo pracovného priestoru",
open_workspace_switcher: "Otvoriť prepínač pracovného priestoru",
open_user_menu: "Otvoriť používateľské menu",
open_command_palette: "Otvoriť paletu príkazov",
open_extended_sidebar: "Otvoriť rozšírený bočný panel",
close_extended_sidebar: "Zavrieť rozšírený bočný panel",
create_favorites_folder: "Vytvoriť priečinok obľúbených",
open_folder: "Otvoriť priečinok",
close_folder: "Zavrieť priečinok",
open_favorites_menu: "Otvoriť menu obľúbených",
close_favorites_menu: "Zavrieť menu obľúbených",
enter_folder_name: "Zadajte názov priečinka",
create_new_project: "Vytvoriť nový projekt",
open_projects_menu: "Otvoriť menu projektov",
close_projects_menu: "Zavrieť menu projektov",
toggle_quick_actions_menu: "Prepnúť menu rýchlych akcií",
open_project_menu: "Otvoriť menu projektu",
close_project_menu: "Zavrieť menu projektu",
collapse_sidebar: "Zbaliť bočný panel",
expand_sidebar: "Rozbaliť bočný panel",
edition_badge: "Otvoriť modal platených plánov",
},
auth_forms: {
clear_email: "Vymazať e-mail",
show_password: "Zobraziť heslo",
hide_password: "Skryť heslo",
close_alert: "Zavrieť upozornenie",
close_popover: "Zavrieť vyskakovacie okno",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Çalışma alanı logosu",
open_workspace_switcher: "Çalışma alanı değiştiricisini aç",
open_user_menu: "Kullanıcı menüsünü aç",
open_command_palette: "Komut paletini aç",
open_extended_sidebar: "Genişletilmiş kenar çubuğunu aç",
close_extended_sidebar: "Genişletilmiş kenar çubuğunu kapat",
create_favorites_folder: "Favoriler klasörü oluştur",
open_folder: "Klasörü aç",
close_folder: "Klasörü kapat",
open_favorites_menu: "Favoriler menüsünü aç",
close_favorites_menu: "Favoriler menüsünü kapat",
enter_folder_name: "Klasör adını girin",
create_new_project: "Yeni proje oluştur",
open_projects_menu: "Projeler menüsünü aç",
close_projects_menu: "Projeler menüsünü kapat",
toggle_quick_actions_menu: "Hızlı eylemler menüsünü aç/kapat",
open_project_menu: "Proje menüsünü aç",
close_project_menu: "Proje menüsünü kapat",
collapse_sidebar: "Kenar çubuğunu daralt",
expand_sidebar: "Kenar çubuğunu genişlet",
edition_badge: "Ücretli planlar modalını aç",
},
auth_forms: {
clear_email: "E-postayı temizle",
show_password: "Şifreyi göster",
hide_password: "Şifreyi gizle",
close_alert: "Uyarıyı kapat",
close_popover: "Açılır pencereyi kapat",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Логотип робочого простору",
open_workspace_switcher: "Відкрити перемикач робочого простору",
open_user_menu: "Відкрити меню користувача",
open_command_palette: "Відкрити палітру команд",
open_extended_sidebar: "Відкрити розширену бічну панель",
close_extended_sidebar: "Закрити розширену бічну панель",
create_favorites_folder: "Створити папку улюблених",
open_folder: "Відкрити папку",
close_folder: "Закрити папку",
open_favorites_menu: "Відкрити меню улюблених",
close_favorites_menu: "Закрити меню улюблених",
enter_folder_name: "Введіть назву папки",
create_new_project: "Створити новий проект",
open_projects_menu: "Відкрити меню проектів",
close_projects_menu: "Закрити меню проектів",
toggle_quick_actions_menu: "Перемкнути меню швидких дій",
open_project_menu: "Відкрити меню проекту",
close_project_menu: "Закрити меню проекту",
collapse_sidebar: "Згорнути бічну панель",
expand_sidebar: "Розгорнути бічну панель",
edition_badge: "Відкрити модал платних планів",
},
auth_forms: {
clear_email: "Очистити email",
show_password: "Показати пароль",
hide_password: "Приховати пароль",
close_alert: "Закрити сповіщення",
close_popover: "Закрити спливаюче вікно",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "Logo không gian làm việc",
open_workspace_switcher: "Mở trình chuyển đổi không gian làm việc",
open_user_menu: "Mở menu người dùng",
open_command_palette: "Mở bảng lệnh",
open_extended_sidebar: "Mở thanh bên mở rộng",
close_extended_sidebar: "Đóng thanh bên mở rộng",
create_favorites_folder: "Tạo thư mục yêu thích",
open_folder: "Mở thư mục",
close_folder: "Đóng thư mục",
open_favorites_menu: "Mở menu yêu thích",
close_favorites_menu: "Đóng menu yêu thích",
enter_folder_name: "Nhập tên thư mục",
create_new_project: "Tạo dự án mới",
open_projects_menu: "Mở menu dự án",
close_projects_menu: "Đóng menu dự án",
toggle_quick_actions_menu: "Bật/tắt menu hành động nhanh",
open_project_menu: "Mở menu dự án",
close_project_menu: "Đóng menu dự án",
collapse_sidebar: "Thu gọn thanh bên",
expand_sidebar: "Mở rộng thanh bên",
edition_badge: "Mở modal gói trả phí",
},
auth_forms: {
clear_email: "Xóa email",
show_password: "Hiển thị mật khẩu",
hide_password: "Ẩn mật khẩu",
close_alert: "Đóng cảnh báo",
close_popover: "Đóng popover",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "工作空间徽标",
open_workspace_switcher: "打开工作空间切换器",
open_user_menu: "打开用户菜单",
open_command_palette: "打开命令面板",
open_extended_sidebar: "打开扩展侧边栏",
close_extended_sidebar: "关闭扩展侧边栏",
create_favorites_folder: "创建收藏夹文件夹",
open_folder: "打开文件夹",
close_folder: "关闭文件夹",
open_favorites_menu: "打开收藏夹菜单",
close_favorites_menu: "关闭收藏夹菜单",
enter_folder_name: "输入文件夹名称",
create_new_project: "创建新项目",
open_projects_menu: "打开项目菜单",
close_projects_menu: "关闭项目菜单",
toggle_quick_actions_menu: "切换快速操作菜单",
open_project_menu: "打开项目菜单",
close_project_menu: "关闭项目菜单",
collapse_sidebar: "折叠侧边栏",
expand_sidebar: "展开侧边栏",
edition_badge: "打开付费计划模态框",
},
auth_forms: {
clear_email: "清除邮箱",
show_password: "显示密码",
hide_password: "隐藏密码",
close_alert: "关闭警告",
close_popover: "关闭弹出框",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
export default {
aria_labels: {
projects_sidebar: {
workspace_logo: "工作空間標誌",
open_workspace_switcher: "打開工作空間切換器",
open_user_menu: "打開用戶選單",
open_command_palette: "打開命令面板",
open_extended_sidebar: "打開擴展側邊欄",
close_extended_sidebar: "關閉擴展側邊欄",
create_favorites_folder: "創建收藏夾文件夾",
open_folder: "打開文件夾",
close_folder: "關閉文件夾",
open_favorites_menu: "打開收藏夾選單",
close_favorites_menu: "關閉收藏夾選單",
enter_folder_name: "輸入文件夾名稱",
create_new_project: "創建新項目",
open_projects_menu: "打開項目選單",
close_projects_menu: "關閉項目選單",
toggle_quick_actions_menu: "切換快速操作選單",
open_project_menu: "打開項目選單",
close_project_menu: "關閉項目選單",
collapse_sidebar: "摺疊側邊欄",
expand_sidebar: "展開側邊欄",
edition_badge: "打開付費計劃模態框",
},
auth_forms: {
clear_email: "清除電子郵件",
show_password: "顯示密碼",
hide_password: "隱藏密碼",
close_alert: "關閉警告",
close_popover: "關閉彈出框",
},
},
} as const;

View File

@@ -0,0 +1 @@
export default {} as const;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
import IntlMessageFormat from "intl-messageformat";
import { get, merge } from "lodash-es";
import { makeAutoObservable, runInAction } from "mobx";
// constants
import { FALLBACK_LANGUAGE, SUPPORTED_LANGUAGES, LANGUAGE_STORAGE_KEY, ETranslationFiles } from "../constants";
// core translations imports
import { enCore, locales } from "../locales";
// types
import { TLanguage, ILanguageOption, ITranslations } from "../types";
/**
* Mobx store class for handling translations and language changes in the application
* Provides methods to translate keys with params and change the language
* Uses IntlMessageFormat to format the translations
*/
export class TranslationStore {
// Core translations that are always loaded
private coreTranslations: ITranslations = {
en: enCore,
};
// List of translations for each language
private translations: ITranslations = {};
// Cache for IntlMessageFormat instances
private messageCache: Map<string, IntlMessageFormat> = new Map();
// Current language
currentLocale: TLanguage = FALLBACK_LANGUAGE;
// Loading state
isLoading: boolean = true;
isInitialized: boolean = false;
// Set of loaded languages
private loadedLanguages: Set<TLanguage> = new Set();
/**
* Constructor for the TranslationStore class
*/
constructor() {
makeAutoObservable(this);
// Initialize with core translations immediately
this.translations = this.coreTranslations;
// Initialize language
this.initializeLanguage();
// Load all the translations
this.loadTranslations();
}
/** Initializes the language based on the local storage or browser language */
private initializeLanguage() {
if (typeof window === "undefined") return;
const savedLocale = localStorage.getItem(LANGUAGE_STORAGE_KEY) as TLanguage;
if (this.isValidLanguage(savedLocale)) {
this.setLanguage(savedLocale);
return;
}
// Fallback to default language
this.setLanguage(FALLBACK_LANGUAGE);
}
/** Loads the translations for the current language */
private async loadTranslations(): Promise<void> {
try {
// Set initialized to true (Core translations are already loaded)
runInAction(() => {
this.isInitialized = true;
});
// Load current and fallback languages in parallel
await this.loadPrimaryLanguages();
// Load all remaining languages in parallel
this.loadRemainingLanguages();
} catch (error) {
console.error("Failed in translation initialization:", error);
runInAction(() => {
this.isLoading = false;
});
}
}
private async loadPrimaryLanguages(): Promise<void> {
try {
// Load current and fallback languages in parallel
const languagesToLoad = new Set<TLanguage>([this.currentLocale]);
// Add fallback language only if different from current
if (this.currentLocale !== FALLBACK_LANGUAGE) {
languagesToLoad.add(FALLBACK_LANGUAGE);
}
// Load all primary languages in parallel
const loadPromises = Array.from(languagesToLoad).map((lang) => this.loadLanguageTranslations(lang));
await Promise.all(loadPromises);
// Update loading state
runInAction(() => {
this.isLoading = false;
});
} catch (error) {
console.error("Failed to load primary languages:", error);
runInAction(() => {
this.isLoading = false;
});
}
}
private loadRemainingLanguages(): void {
const remainingLanguages = SUPPORTED_LANGUAGES.map((lang) => lang.value).filter(
(lang) =>
!this.loadedLanguages.has(lang as TLanguage) && lang !== this.currentLocale && lang !== FALLBACK_LANGUAGE
);
// Load all remaining languages in parallel
Promise.all(remainingLanguages.map((lang) => this.loadLanguageTranslations(lang as TLanguage))).catch((error) => {
console.error("Failed to load some remaining languages:", error);
});
}
private async loadLanguageTranslations(language: TLanguage): Promise<void> {
// Skip if already loaded
if (this.loadedLanguages.has(language)) return;
try {
const translations = await this.importLanguageFile(language);
runInAction(() => {
// Use lodash merge for deep merging
this.translations[language] = merge({}, this.coreTranslations[language] || {}, translations.default);
// Add to loaded languages
this.loadedLanguages.add(language);
// Clear cache
this.messageCache.clear();
});
} catch (error) {
console.error(`Failed to load translations for ${language}:`, error);
}
}
/**
* Helper function to import and merge multiple translation files for a language
* @param language - The language code
* @param files - Array of file names to import (without .json extension)
* @returns Promise that resolves to merged translations
*/
private async importAndMergeFiles(language: TLanguage, files: string[]) {
try {
const localeData = locales[language as keyof typeof locales];
if (!localeData) {
throw new Error(`Locale data not found for language: ${language}`);
}
// Filter out files that don't exist for this language
const availableFiles = files.filter((file) => {
const fileKey = file as keyof typeof localeData;
return fileKey in localeData;
});
const importPromises = availableFiles.map((file) => {
const fileKey = file as keyof typeof localeData;
return localeData[fileKey]();
});
const modules = await Promise.all(importPromises);
const merged = modules.reduce((acc: any, module: any) => merge(acc, module.default), {});
return { default: merged };
} catch (error) {
throw new Error(`Failed to import and merge files for ${language}: ${error}`);
}
}
/**
* Imports the translations for the given language
* @param language - The language to import the translations for
* @returns {Promise<any>}
*/
private async importLanguageFile(language: TLanguage) {
const files = Object.values(ETranslationFiles);
return this.importAndMergeFiles(language, files);
}
/** Checks if the language is valid based on the supported languages */
private isValidLanguage(lang: string | null): lang is TLanguage {
return lang !== null && this.availableLanguages.some((l) => l.value === lang);
}
/**
* Gets the cache key for the given key and locale
* @param key - the key to get the cache key for
* @param locale - the locale to get the cache key for
* @returns the cache key for the given key and locale
*/
private getCacheKey(key: string, locale: TLanguage): string {
return `${locale}:${key}`;
}
/**
* Gets the IntlMessageFormat instance for the given key and locale
* Returns cached instance if available
*/
private getMessageInstance(key: string, locale: TLanguage): IntlMessageFormat | null {
const cacheKey = this.getCacheKey(key, locale);
// Check if the cache already has the key
if (this.messageCache.has(cacheKey)) {
return this.messageCache.get(cacheKey) || null;
}
// Get the message from the translations
const message = get(this.translations[locale], key);
if (typeof message !== "string") return null;
try {
const formatter = new IntlMessageFormat(message, locale);
this.messageCache.set(cacheKey, formatter);
return formatter;
} catch (error) {
console.error(`Failed to create message formatter for key "${key}":`, error);
return null;
}
}
/**
* Translates a key with params using the current locale
* Falls back to the default language if the translation is not found
* Returns the key itself if the translation is not found
* @param key - The key to translate
* @param params - The params to format the translation with
* @returns The translated string
*/
t(key: string, params?: Record<string, unknown>): string {
try {
// Try current locale
let formatter = this.getMessageInstance(key, this.currentLocale);
// Fallback to default language if necessary
if (!formatter && this.currentLocale !== FALLBACK_LANGUAGE) {
formatter = this.getMessageInstance(key, FALLBACK_LANGUAGE);
}
// If we have a formatter, use it
if (formatter) {
return formatter.format(params || {}) as string;
}
// Last resort: return the key itself
return key;
} catch (error) {
console.error(`Translation error for key "${key}":`, error);
return key;
}
}
/**
* Sets the current language and updates the translations
* @param lng - The new language
*/
async setLanguage(lng: TLanguage): Promise<void> {
try {
if (!this.isValidLanguage(lng)) {
throw new Error(`Invalid language: ${lng}`);
}
// Safeguard in case background loading failed
if (!this.loadedLanguages.has(lng)) {
await this.loadLanguageTranslations(lng);
}
if (typeof window !== "undefined") {
localStorage.setItem(LANGUAGE_STORAGE_KEY, lng);
document.documentElement.lang = lng;
}
runInAction(() => {
this.currentLocale = lng;
this.messageCache.clear(); // Clear cache when language changes
});
} catch (error) {
console.error("Failed to set language:", error);
}
}
/**
* Gets the available language options for the dropdown
* @returns An array of language options
*/
get availableLanguages(): ILanguageOption[] {
return SUPPORTED_LANGUAGES;
}
}

View File

@@ -0,0 +1,2 @@
export * from "./language";
export * from "./translation";

View File

@@ -0,0 +1,25 @@
export type TLanguage =
| "en"
| "fr"
| "es"
| "ja"
| "zh-CN"
| "zh-TW"
| "ru"
| "it"
| "cs"
| "sk"
| "de"
| "ua"
| "pl"
| "ko"
| "pt-BR"
| "id"
| "ro"
| "vi-VN"
| "tr-TR";
export interface ILanguageOption {
label: string;
value: TLanguage;
}

View File

@@ -0,0 +1,7 @@
export interface ITranslation {
[key: string]: string | ITranslation;
}
export interface ITranslations {
[locale: string]: ITranslation;
}

View File

@@ -0,0 +1,10 @@
{
"extends": "@plane/typescript-config/react-library.json",
"compilerOptions": {
"jsx": "react",
"lib": ["esnext", "dom"],
"resolveJsonModule": true
},
"include": ["./src"],
"exclude": ["dist", "build", "node_modules"]
}

View File

@@ -0,0 +1,11 @@
import { defineConfig } from "tsdown";
export default defineConfig({
entry: ["src/index.ts"],
outDir: "dist",
format: ["esm", "cjs"],
exports: true,
dts: true,
clean: true,
sourcemap: true,
});