mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-03-22 23:30:36 +08:00
feat(i18n): automatic RTL layout for Arabic, Persian, and Urdu + complete Arabic translations (#14624)
## Changes ### RTL Support (automatic, locale-driven) - Add `rtl?: boolean` metadata to locale definitions in `SUPPORTED_LANGUAGES` - Set `rtl: true` for Arabic (`ar`), Persian (`fa`), and Urdu (`ur`) - Automatically set `document.documentElement.dir` based on locale RTL metadata on language change - Remove hardcoded `lang="en"` from HTML template — JS now controls both `lang` and `dir` ### Arabic Translations - Add 100 missing keys to `ar.json` (Calendar integration, Doc Analytics, MCP Server, AI Chat, and more) - Arabic locale now has 2,313/2,313 keys (100% coverage, matches `en.json` exactly) ## Testing Switching to Arabic/Persian/Urdu now automatically flips the entire UI layout to RTL without any manual feature flag. Fixes #7099 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Right-to-Left (RTL) support for Arabic, Persian, and Urdu with automatic document direction and language attributes when a language is selected. * **Refactor** * Centralized and reordered internal language handling so document language and direction are applied earlier and consistently. * **Chore** * Set a default text direction attribute on the base HTML template. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -54,13 +54,22 @@ export class I18n extends Entity {
|
||||
constructor(private readonly cache: GlobalCache) {
|
||||
super();
|
||||
this.i18n.on('languageChanged', (language: Language) => {
|
||||
document.documentElement.lang = language;
|
||||
this.applyDocumentLanguage(language);
|
||||
this.cache.set('i18n_lng', language);
|
||||
});
|
||||
}
|
||||
|
||||
init() {
|
||||
this.changeLanguage(this.currentLanguageKey$.value ?? 'en');
|
||||
const language = this.currentLanguageKey$.value ?? 'en';
|
||||
this.applyDocumentLanguage(language);
|
||||
this.changeLanguage(language);
|
||||
}
|
||||
|
||||
private applyDocumentLanguage(language: Language) {
|
||||
document.documentElement.lang = language;
|
||||
document.documentElement.dir = SUPPORTED_LANGUAGES[language]?.rtl
|
||||
? 'rtl'
|
||||
: 'ltr';
|
||||
}
|
||||
|
||||
changeLanguage = effect(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@ export const SUPPORTED_LANGUAGES: Record<
|
||||
name: string;
|
||||
originalName: string;
|
||||
flagEmoji: string;
|
||||
rtl?: boolean;
|
||||
resource:
|
||||
| LanguageResource
|
||||
| (() => Promise<{ default: Partial<LanguageResource> }>);
|
||||
@@ -149,18 +150,21 @@ export const SUPPORTED_LANGUAGES: Record<
|
||||
name: 'Urdu',
|
||||
originalName: 'اردو',
|
||||
flagEmoji: '🇵🇰',
|
||||
rtl: true,
|
||||
resource: () => import('./ur.json'),
|
||||
},
|
||||
ar: {
|
||||
name: 'Arabic',
|
||||
originalName: 'العربية',
|
||||
flagEmoji: '🇸🇦',
|
||||
rtl: true,
|
||||
resource: () => import('./ar.json'),
|
||||
},
|
||||
fa: {
|
||||
name: 'Persian',
|
||||
originalName: 'فارسی',
|
||||
flagEmoji: '🇮🇷',
|
||||
rtl: true,
|
||||
resource: () => import('./fa.json'),
|
||||
},
|
||||
uk: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
|
||||
Reference in New Issue
Block a user