Skip to content

Commit 269ac69

Browse files
vamsikrishnamathalasriramveeraghantaanmolsinghbhatiaprateekshourya29gakshita
authored andcommitted
[WEB-2870]feat: language support (#6215)
* fix: adding language support package * fix: language support implementation using mobx * fix: adding more languages for support * fix: profile settings translations * feat: added language support for sidebar and user settings * feat: added language support for deactivation modal * fix: added project sync after transfer issues (#6200) * code refactor and improvement (#6203) * chore: package code refactoring * chore: component restructuring and refactor * chore: comment create improvement * refactor: enhance workspace and project wrapper modularity (#6207) * [WEB-2678]feat: added functionality to add labels directly from dropdown (#6211) * enhancement:added functionality to add features directly from dropdown * fix: fixed import order * fix: fixed lint errors * chore: added common component for project activity (#6212) * chore: added common component for project activity * fix: added enum * fix: added enum for initiatives * - Do not clear temp files that are locked. (#6214) - Handle edge cases in sync workspace * fix: labels empty state for drop down (#6216) * refactor: remove cn helper function from the editor package (#6217) * * feat: added language support to issue create modal in sidebar * fix: project activity type * * fix: added missing translations * fix: modified translation for plurals * fix: fixed spanish translation * dev: language type error in space user profile types * fix: type fixes * chore: added alpha tag --------- Co-authored-by: sriram veeraghanta <[email protected]> Co-authored-by: Anmol Singh Bhatia <[email protected]> Co-authored-by: Prateek Shourya <[email protected]> Co-authored-by: Akshita Goyal <[email protected]> Co-authored-by: Satish Gandham <[email protected]> Co-authored-by: Aaryan Khandelwal <[email protected]> Co-authored-by: gurusinath <[email protected]>
1 parent e22f5ce commit 269ac69

File tree

84 files changed

+2588
-873
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2588
-873
lines changed

packages/constants/src/workspace.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export const ORGANIZATION_SIZE = [
2-
"Just myself",
2+
"Just myself", // TODO: translate
33
"2-10",
44
"11-50",
55
"51-200",

packages/i18n/.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
build/*
2+
dist/*
3+
out/*

packages/i18n/.eslintrc.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/** @type {import("eslint").Linter.Config} */
2+
module.exports = {
3+
root: true,
4+
extends: ["@plane/eslint-config/library.js"],
5+
parser: "@typescript-eslint/parser",
6+
parserOptions: {
7+
project: true,
8+
},
9+
};

packages/i18n/.prettierignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.turbo
2+
out/
3+
dist/
4+
build/

packages/i18n/.prettierrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"printWidth": 120,
3+
"tabWidth": 2,
4+
"trailingComma": "es5"
5+
}

packages/i18n/package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@plane/i18n",
3+
"version": "0.24.1",
4+
"description": "I18n shared across multiple apps internally",
5+
"private": true,
6+
"main": "./src/index.ts",
7+
"types": "./src/index.ts",
8+
"scripts": {
9+
"lint": "eslint src --ext .ts,.tsx",
10+
"lint:errors": "eslint src --ext .ts,.tsx --quiet"
11+
},
12+
"dependencies": {
13+
"@plane/utils": "*"
14+
},
15+
"devDependencies": {
16+
"@plane/eslint-config": "*",
17+
"@types/node": "^22.5.4",
18+
"typescript": "^5.3.3"
19+
}
20+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { observer } from "mobx-react";
2+
import React, { createContext, useEffect } from "react";
3+
import { Language, languages } from "../config";
4+
import { TranslationStore } from "./store";
5+
6+
// Create the store instance
7+
const translationStore = new TranslationStore();
8+
9+
// Create Context
10+
export const TranslationContext = createContext<TranslationStore>(translationStore);
11+
12+
export const TranslationProvider = observer(({ children }: { children: React.ReactNode }) => {
13+
// Handle storage events for cross-tab synchronization
14+
useEffect(() => {
15+
const handleStorageChange = (event: StorageEvent) => {
16+
if (event.key === "userLanguage" && event.newValue) {
17+
const newLang = event.newValue as Language;
18+
if (languages.includes(newLang)) {
19+
translationStore.setLanguage(newLang);
20+
}
21+
}
22+
};
23+
24+
window.addEventListener("storage", handleStorageChange);
25+
return () => window.removeEventListener("storage", handleStorageChange);
26+
}, []);
27+
28+
return <TranslationContext.Provider value={translationStore}>{children}</TranslationContext.Provider>;
29+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { makeObservable, observable } from "mobx";
2+
import { Language, fallbackLng, languages, translations } from "../config";
3+
4+
export class TranslationStore {
5+
currentLocale: Language = fallbackLng;
6+
7+
constructor() {
8+
makeObservable(this, {
9+
currentLocale: observable.ref,
10+
});
11+
this.initializeLanguage();
12+
}
13+
14+
get availableLanguages() {
15+
return languages;
16+
}
17+
18+
t(key: string) {
19+
return translations[this.currentLocale]?.[key] || translations[fallbackLng][key] || key;
20+
}
21+
22+
setLanguage(lng: Language) {
23+
try {
24+
localStorage.setItem("userLanguage", lng);
25+
this.currentLocale = lng;
26+
} catch (error) {
27+
console.error(error);
28+
}
29+
}
30+
31+
initializeLanguage() {
32+
if (typeof window === "undefined") return;
33+
const savedLocale = localStorage.getItem("userLanguage") as Language;
34+
if (savedLocale && languages.includes(savedLocale)) {
35+
this.setLanguage(savedLocale);
36+
} else {
37+
const browserLang = navigator.language.split("-")[0] as Language;
38+
const newLocale = languages.includes(browserLang as Language) ? (browserLang as Language) : fallbackLng;
39+
this.setLanguage(newLocale);
40+
}
41+
}
42+
}

packages/i18n/src/config/index.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import en from "../locales/en/translations.json";
2+
import fr from "../locales/fr/translations.json";
3+
import es from "../locales/es/translations.json";
4+
import ja from "../locales/ja/translations.json";
5+
6+
export type Language = (typeof languages)[number];
7+
export type Translations = {
8+
[key: string]: {
9+
[key: string]: string;
10+
};
11+
};
12+
13+
export const fallbackLng = "en";
14+
export const languages = ["en", "fr", "es", "ja"] as const;
15+
export const translations: Translations = {
16+
en,
17+
fr,
18+
es,
19+
ja,
20+
};
21+
22+
export const SUPPORTED_LANGUAGES = [
23+
{
24+
label: "English",
25+
value: "en",
26+
},
27+
{
28+
label: "French",
29+
value: "fr",
30+
},
31+
{
32+
label: "Spanish",
33+
value: "es",
34+
},
35+
{
36+
label: "Japanese",
37+
value: "ja",
38+
},
39+
];

packages/i18n/src/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./use-translation";

0 commit comments

Comments
 (0)