@intlayer/docs 7.3.3 → 7.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  createdAt: 2025-11-24
3
3
  updatedAt: 2025-11-24
4
- title: المترجم مقابل التدوين التصريحي في التدويل
5
- description: استكشاف المقايضات المعمارية بين التدويل "السحري" المعتمد على المترجم وإدارة المحتوى التصريحية الصريحة.
4
+ title: المترجم مقابل التدوين التصريحي للتدويل
5
+ description: استكشاف التنازلات المعمارية بين التدويل "السحري" المعتمد على المترجم وإدارة المحتوى التصريحية الصريحة.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - التدويل
@@ -12,7 +12,7 @@ keywords:
12
12
  - React
13
13
  - i18n
14
14
  - المترجم
15
- - تدويني
15
+ - تصريحي
16
16
  slugs:
17
17
  - blog
18
18
  - compiler-vs-declarative-i18n
@@ -20,118 +20,201 @@ slugs:
20
20
 
21
21
  # الحجج المؤيدة والمعارضة للتدويل المعتمد على المترجم
22
22
 
23
- إذا كنت تبني تطبيقات ويب لأكثر من عقد من الزمن، فأنت تعلم أن التدويل (i18n) كان دائمًا نقطة احتكاك. غالبًا ما تكون مهمة لا يرغب أحد في القيام بها استخراج النصوص، إدارة ملفات JSON، والقلق بشأن قواعد الجمع والتعدد.
23
+ إذا كنت تبني تطبيقات ويب لأكثر من عقد من الزمن، فأنت تعلم أن التدويل (i18n) كان دائمًا نقطة احتكاك. غالبًا ما تكون مهمة لا يرغب أحد في القيام بها - استخراج النصوص، إدارة ملفات JSON، والقلق بشأن قواعد الجمع.
24
24
 
25
- مؤخرًا، ظهرت موجة جديدة من أدوات التدويل "المعتمدة على المترجم"، واعدة بجعل هذه المعاناة تختفي. العرض مغرٍ: **فقط اكتب النص في مكوناتك، ودع أداة البناء تتولى الباقي.** لا مفاتيح، لا استيرادات، فقط سحر.
25
+ مؤخرًا، ظهرت موجة جديدة من أدوات التدويل **المعتمدة على المترجم**، والتي تعد بجعل هذه المعاناة تختفي. العرض مغرٍ: **فقط اكتب النصوص في مكوناتك، ودع أداة البناء تتولى الباقي.** لا مفاتيح، لا استيرادات، فقط سحر.
26
26
 
27
27
  ولكن كما هو الحال مع جميع التجريدات في هندسة البرمجيات، يأتي السحر بثمن.
28
28
 
29
- في هذه التدوينة، سوف نستكشف التحول من المكتبات التصريحية إلى النهج المعتمد على المترجم، والديون المعمارية الخفية التي يقدمونها، ولماذا قد يكون الطريق "الممل" لا يزال أفضل طريقة للتطبيقات المهنية.
29
+ في هذه التدوينة، سوف نستكشف التحول من المكتبات التصريحية إلى النهج المعتمد على المترجم، والديون المعمارية الخفية التي يقدمونها، ولماذا قد تظل الطريقة "المملة" هي الأفضل للتطبيقات المهنية.
30
30
 
31
- ## لمحة تاريخية عن الترجمة
31
+ ## جدول المحتويات
32
32
 
33
- لفهم مكاننا الحالي، علينا أن ننظر إلى الوراء حيث بدأنا.
33
+ <TOC/>
34
34
 
35
- حوالي عامي 2011–2012، كان مشهد JavaScript مختلفًا تمامًا. لم تكن أدوات التجميع كما نعرفها اليوم (Webpack، Vite) موجودة أو كانت في مراحلها الأولى. كنا نلصق السكريبتات معًا في المتصفح. في هذه الحقبة، وُلدت مكتبات مثل **i18next**.
35
+ ## لمحة تاريخية عن التدويل
36
36
 
37
- لقد حلوا المشكلة بالطريقة الوحيدة الممكنة في ذلك الوقت: **القواميس أثناء وقت التشغيل**. كنت تقوم بتحميل كائن JSON ضخم في الذاكرة، وكانت دالة تبحث عن المفاتيح أثناء التنفيذ. كان ذلك موثوقًا وصريحًا، ويعمل في كل مكان.
37
+ لفهم مكاننا الحالي، يجب أن ننظر إلى الوراء حيث بدأنا.
38
38
 
39
- تقدم سريعًا إلى اليوم. لدينا مترجمات قوية (SWC، أدوات تجميع مبنية على Rust) يمكنها تحليل أشجار البنية المجردة (AST) في غضون مللي ثانية. هذه القوة ولدت فكرة جديدة: _لماذا ندير المفاتيح يدويًا؟ لماذا لا يستطيع المترجم فقط رؤية النص "Hello World" واستبداله لنا؟_
39
+ في الفترة ما بين 2011 و2012، كان مشهد جافا سكريبت مختلفًا تمامًا. لم تكن أدوات التجميع كما نعرفها اليوم (Webpack، Vite) موجودة أو كانت في مراحلها الأولى. كنا نلصق السكريبتات معًا في المتصفح. في هذه الحقبة، وُلدت مكتبات مثل **i18next**.
40
40
 
41
- وهكذا وُلدت الترجمة المعتمدة على المترجم (Compiler-based i18n).
41
+ لقد حلت المشكلة بالطريقة الوحيدة الممكنة في ذلك الوقت: **القواميس أثناء وقت التشغيل**. كنت تقوم بتحميل كائن JSON ضخم في الذاكرة، وكانت دالة تبحث عن المفاتيح أثناء التنفيذ. كانت طريقة موثوقة وصريحة وتعمل في كل مكان.
42
+
43
+ تقدم سريعًا إلى اليوم. لدينا مترجمات قوية (SWC، أدوات تجميع مبنية على Rust) يمكنها تحليل أشجار البنية المجردة (AST) في غضون ميلي ثانية. هذه القوة ولدت فكرة جديدة: _لماذا ندير المفاتيح يدويًا؟ لماذا لا يستطيع المترجم فقط رؤية النص "Hello World" واستبداله لنا؟_
44
+
45
+ وهكذا وُلد التدويل المعتمد على المترجم.
46
+
47
+ > **مثال على التدويل المعتمد على المترجم:**
48
+ >
49
+ > - Paraglide (وحدات تم تقليلها باستخدام tree-shaking تقوم بترجمة كل رسالة إلى دالة ESM صغيرة بحيث يمكن لأدوات التجميع حذف اللغات والمفاتيح غير المستخدمة تلقائيًا. تقوم باستيراد الرسائل كدوال بدلاً من البحث عن المفاتيح كنصوص.)
50
+ > - LinguiJS (مترجم من الماكرو إلى الدالة يعيد كتابة ماكرو الرسائل مثل `<Trans>` إلى استدعاءات دوال جافاسكريبت عادية أثناء وقت البناء. تحصل على صيغة ICU/MessageFormat مع بصمة تشغيل صغيرة جدًا.)
51
+ > - Lingo.dev (يركز على أتمتة خط أنابيب التوطين عن طريق حقن المحتوى المترجم مباشرة أثناء بناء تطبيق React الخاص بك. يمكنه توليد الترجمات تلقائيًا باستخدام الذكاء الاصطناعي والتكامل مباشرة في CI/CD.)
52
+ > - Wuchale (معالج مسبق يركز على Svelte يقوم باستخراج النصوص المضمنة في ملفات .svelte ويحولها إلى دوال ترجمة بدون تغليف. يتجنب استخدام مفاتيح نصية، ويفصل منطق استخراج المحتوى تمامًا عن وقت تشغيل التطبيق الرئيسي.)
53
+ > - Intlayer (مترجم / أداة CLI للاستخراج تقوم بتحليل مكوناتك، وتوليد قواميس ذات أنواع، ويمكنها اختياريًا إعادة كتابة الكود لاستخدام محتوى Intlayer صريح. الهدف هو استخدام المترجم للسرعة مع الحفاظ على جوهر إعلاني مستقل عن الإطار.)
54
+
55
+ > **مثال على التوطين الإعلاني:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (المعيار الصناعي الناضج الذي يستخدم قواميس JSON وقت التشغيل ونظام إضافات واسع)
58
+ > - react-intl (جزء من مكتبة FormatJS، يركز على صياغة رسائل ICU القياسية وتنسيق البيانات الصارم)
59
+ > - next-intl (محسّن خصيصًا لـ Next.js مع تكامل مع App Router ومكونات React Server)
60
+ > - vue-i18n / @nuxt/i18n (الحل القياسي في نظام Vue البيئي الذي يقدم كتل ترجمة على مستوى المكونات وتكامل تفاعلي محكم)
61
+ > - svelte-i18n (غلاف خفيف حول مخازن Svelte للترجمات التفاعلية وقت التشغيل)
62
+ > - angular-translate (مكتبة الترجمة الديناميكية القديمة التي تعتمد على البحث عن المفاتيح وقت التشغيل بدلاً من الدمج أثناء البناء)
63
+ > - angular-i18n (النهج الأصلي لـ Angular المسبق للوقت الذي يدمج ملفات XLIFF مباشرة في القوالب أثناء البناء)
64
+ > - Tolgee (يجمع بين الكود التصريحي وSDK ضمن السياق لتحرير "انقر للترجمة" مباشرة في واجهة المستخدم)
65
+ > - Intlayer (نهج لكل مكون، يستخدم ملفات إعلانات المحتوى التي تمكّن من tree-shaking أصلي والتحقق من TypeScript)
66
+
67
+ ## مترجم Intlayer
68
+
69
+ على الرغم من أن **Intlayer** هو حل يشجع أساسًا على **النهج التصريحي** لمحتواك، إلا أنه يتضمن مترجمًا للمساعدة في تسريع التطوير أو تسهيل النماذج الأولية السريعة.
70
+
71
+ يقوم مترجم Intlayer بتصفح شجرة البنية المجردة (AST) لمكونات React أو Vue أو Svelte الخاصة بك، بالإضافة إلى ملفات JavaScript/TypeScript الأخرى. دوره هو اكتشاف السلاسل النصية المضمنة واستخراجها إلى إعلانات `.content` مخصصة.
72
+
73
+ > لمزيد من التفاصيل، اطلع على الوثائق: [وثائق مترجم Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ar/compiler.md)
42
74
 
43
75
  ## جاذبية المترجم (النهج "السحري")
44
76
 
45
- هناك سبب يجعل هذا النهج الجديد شائعًا. بالنسبة للمطور، تكون التجربة مذهلة.
77
+ هناك سبب يجعل هذا النهج الجديد شائعًا. بالنسبة للمطور، التجربة مذهلة.
46
78
 
47
79
  ### 1. السرعة و"التدفق"
48
80
 
49
- عندما تكون في حالة تركيز، التوقف للتفكير في اسم متغير (`home_hero_title_v2`) يكسر تدفقك. مع نهج المترجم، تكتب `<p>Welcome back</p>` وتتابع العمل. الاحتكاك معدوم.
81
+ عندما تكون في حالة تركيز، التوقف للتفكير في اسم متغير دلالي (`home_hero_title_v2`) يكسر تدفقك. مع نهج المترجم، تكتب `<p>Welcome back</p>` وتستمر في العمل. الاحتكاك معدوم.
50
82
 
51
83
  ### 2. مهمة إنقاذ التراث
52
84
 
53
- تخيل أنك ترث قاعدة كود ضخمة تحتوي على 5000 مكون وبدون أي ترجمات. تعديل هذا النظام ليعمل بنظام المفاتيح اليدوي هو كابوس يستمر لأشهر. أداة تعتمد على المترجم تعمل كاستراتيجية إنقاذ، حيث تستخرج آلاف السلاسل النصية فورًا دون الحاجة إلى لمس أي ملف يدويًا.
85
+ تخيل أنك ترث قاعدة كود ضخمة تحتوي على 5000 مكون وبدون أي ترجمات. إعادة تجهيز هذا النظام باستخدام نظام مفاتيح يدوي هو كابوس يستمر لأشهر. أداة تعتمد على المترجم تعمل كاستراتيجية إنقاذ، حيث تستخرج آلاف السلاسل النصية فورًا دون الحاجة إلى لمس أي ملف يدويًا.
54
86
 
55
87
  ### 3. عصر الذكاء الاصطناعي
56
88
 
57
- هذه فائدة حديثة لا ينبغي أن نتجاهلها. مساعدو البرمجة بالذكاء الاصطناعي (مثل Copilot أو ChatGPT) يولدون بشكل طبيعي JSX/HTML قياسي. هم لا يعرفون مخطط مفاتيح الترجمة الخاص بك.
89
+ هذه ميزة حديثة لا ينبغي تجاهلها. مساعدو البرمجة بالذكاء الاصطناعي (مثل Copilot أو ChatGPT) يولدون بشكل طبيعي JSX/HTML قياسي. هم لا يعرفون مخطط مفاتيح الترجمة الخاص بك.
58
90
 
59
91
  - **إعلاني:** عليك إعادة كتابة مخرجات الذكاء الاصطناعي لاستبدال النص بالمفاتيح.
60
92
  - **المترجم:** تقوم بنسخ ولصق كود الذكاء الاصطناعي، ويعمل مباشرة.
61
93
 
62
- ## فحص الواقع: لماذا "السحر" خطير
94
+ ## التحقق من الواقع: لماذا "السحر" خطير
95
+
96
+ بينما تبدو "السحرية" جذابة، إلا أن التجريد يتسرب. الاعتماد على أداة بناء لفهم نية الإنسان يُدخل هشاشة معمارية.
97
+
98
+ ### هشاشة الاستدلال (لعبة التخمين)
99
+
100
+ يجب على المترجم أن يخمن ما هو المحتوى وما هو الكود. هذا يؤدي إلى حالات حافة حيث ينتهي بك الأمر إلى "مقاتلة" الأداة.
101
+
102
+ ضع في اعتبارك هذه السيناريوهات:
103
+
104
+ - هل يتم استخراج `<span className="active"></span>`؟ (إنها سلسلة نصية، لكنها على الأرجح فئة).
105
+ - هل يتم استخراج `<span status="pending"></span>`؟ (إنها قيمة خاصية).
106
+ - هل يتم استخراج `<span>{"Hello World"}</span>`؟ (إنها تعبير جافاسكريبت).
107
+ - هل يتم استخراج `<span>Hello {name}. How are you?</span>`؟ (التضمين معقد).
108
+ - هل يتم استخراج `<span aria-label="Image of cat"></span>`؟ (سمات الوصول تحتاج إلى ترجمة).
109
+ - هل يتم استخراج `<span data-testid="my-element"></span>`؟ (يجب عدم ترجمة معرفات الاختبار).
110
+ - هل يتم استخراج `<MyComponent errorMessage="An error occurred" />`؟
111
+ - هل يتم استخراج `<p>This is a paragraph{" "}\n containing multiple lines</p>`؟
112
+ - هل يتم استخراج نتيجة الدالة `<p>{getStatusMessage()}</p>`؟
113
+ - هل يتم استخراج `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>`؟
114
+ - هل يتم استخراج معرف منتج مثل `<span>AX-99</span>`؟
115
+
116
+ في النهاية، ستضطر إلى إضافة تعليقات محددة (مثل `// ignore-translation`، أو خصائص محددة مثل `data-compiler-ignore="true"`) لمنع ذلك من كسر منطق تطبيقك.
117
+
118
+ ### كيف يتعامل Intlayer مع هذه التعقيدات؟
63
119
 
64
- بينما يبدو "السحر" جذابًا، فإن التجريد يتسرب. الاعتماد على أداة بناء لفهم نية الإنسان يُدخل هشاشة معمارية.
120
+ تستخدم Intlayer نهجًا مختلطًا لاكتشاف ما إذا كان يجب استخراج حقل للترجمة، مع محاولة تقليل الإيجابيات الكاذبة:
65
121
 
66
- ### 1. هشاشة الاستدلال (لعبة التخمين)
122
+ 1. **تحليل AST:** يتحقق من نوع العنصر (مثل التمييز بين `reactNode` أو `label` أو خاصية `title`).
123
+ 2. **التعرف على الأنماط:** يكتشف ما إذا كانت السلسلة تبدأ بحرف كبير أو تحتوي على مسافات، مما يشير إلى أنها على الأرجح نص قابل للقراءة من قبل الإنسان بدلاً من معرف كود.
67
124
 
68
- يجب على المترجم أن يخمن ما هو المحتوى وما هو الكود.
125
+ ### الحد الصعب للبيانات الديناميكية
69
126
 
70
- - هل يتم ترجمة `className="active"`؟ إنها سلسلة نصية.
71
- - هل يتم ترجمة `status="pending"
72
- - هل يتم ترجمة `<MyComponent errorMessage="An error occurred" />`؟
73
- - هل يتم ترجمة معرف منتج مثل `"AX-99"`؟
127
+ يعتمد استخراج المترجم على **التحليل الثابت**. يجب أن يرى السلسلة الحرفية في الكود الخاص بك لتوليد معرف ثابت.
128
+ إذا كانت واجهة برمجة التطبيقات (API) الخاصة بك تُرجع سلسلة رمز خطأ مثل `server_error`، فلا يمكنك ترجمتها باستخدام المترجم (compiler) لأن المترجم لا يعرف بوجود هذه السلسلة أثناء وقت البناء. ستضطر إلى بناء نظام ثانوي "للوقت التشغيلي فقط" خصيصًا للبيانات الديناميكية.
74
129
 
75
- في النهاية، ستجد نفسك "تقاتل" المترجم، مضيفًا تعليقات محددة (مثل `// ignore-translation`) لمنعه من كسر منطق تطبيقك.
130
+ ### نقص التجزئة (chunking)
76
131
 
77
- ### 2. الحد الصعب للبيانات الديناميكية
132
+ بعض المترجمات لا تقوم بتجزئة الترجمات حسب الصفحة. إذا كان المترجم الخاص بك يُنتج ملف JSON كبير لكل لغة (مثل `./lang/en.json`، `./lang/fr.json`، إلخ)، فمن المحتمل أن ينتهي بك الأمر بتحميل محتوى من جميع صفحاتك لصفحة واحدة فقط يتم زيارتها. أيضًا، من المحتمل أن يتم تهيئة كل مكون يستخدم المحتوى الخاص بك بمحتوى أكثر بكثير مما هو ضروري، مما قد يسبب مشاكل في الأداء.
78
133
 
79
- يعتمد استخراج المترجم على **التحليل الثابت**. يجب أن يرى السلسلة النصية الحرفية في كودك لتوليد معرف ثابت.
80
- إذا أعاد API الخاص بك رمز خطأ مثل `server_error`، فلا يمكنك ترجمته باستخدام المترجم لأن المترجم لا يعرف بوجود هذه السلسلة أثناء وقت البناء. تُجبر على بناء نظام ثانوي "للتشغيل فقط" مخصص للبيانات الديناميكية.
134
+ كن حذرًا أيضًا بشأن تحميل ترجماتك بشكل ديناميكي. إذا لم يتم ذلك، فستقوم بتحميل محتوى لجميع اللغات بالإضافة إلى اللغة الحالية.
81
135
 
82
- ### 3. "انفجار القطع" وشلالات الشبكة
136
+ > لتوضيح المشكلة، تخيل موقعًا يحتوي على 10 صفحات و10 لغات (جميعها فريدة بنسبة 100%). ستقوم بتحميل محتوى لـ 99 صفحة إضافية (10 × 10 - 1).
83
137
 
84
- للسماح بعملية tree-shaking، غالبًا ما تقوم أدوات المترجم بتقسيم الترجمات حسب المكون.
138
+ ### "انفجار القطع" وشلالات الشبكة
85
139
 
86
- - **النتيجة:** قد يؤدي عرض صفحة واحدة تحتوي على 50 مكونًا صغيرًا إلى تفعيل **50 طلب HTTP منفصل** لقطع ترجمة صغيرة. حتى مع HTTP/2، يخلق هذا شلالًا في الشبكة يجعل تطبيقك يبدو بطيئًا مقارنة بتحميل حزمة لغة واحدة محسّنة.
140
+ لحل مشكلة تقسيم القطع، تقدم بعض الحلول تقسيمًا حسب المكون، أو حتى حسب المفتاح. ومع ذلك، فإن المشكلة تُحل جزئيًا فقط. النقطة التسويقية لهذه الحلول غالبًا ما تكون "محتواك يتم تنظيفه من غير المستخدم."
87
141
 
88
- ### 4. العبء على أداء وقت التشغيل
142
+ في الواقع، إذا قمت بتحميل المحتوى بشكل ثابت، فإن حلك سيقوم بتنظيف المحتوى غير المستخدم، لكنك ستظل تحصل على محتوى من جميع اللغات محمّلًا مع تطبيقك.
89
143
 
90
- لجعل الترجمات تفاعلية (حتى يتم تحديثها فورًا عند تبديل اللغات)، غالبًا ما يقوم المترجم بحقن خطافات إدارة الحالة في _كل_ مكون.
144
+ فلماذا لا تقوم بتحميله ديناميكيًا؟ نعم، في هذه الحالة ستقوم بتحميل أكثر من المحتوى الضروري، لكن هذا ليس بدون مقايضات.
91
145
 
92
- - **التكلفة:** إذا قمت بعرض قائمة تحتوي على 5000 عنصر، فأنت تقوم بتهيئة 5000 من خطافات `useState` و `useEffect` فقط للنصوص. هذا يستهلك الذاكرة ودورات وحدة المعالجة المركزية التي توفرها المكتبات التصريحية (التي تستخدم عادة مزود Context واحد).
146
+ تحميل المحتوى ديناميكيًا يعزل كل قطعة من المحتوى في جزء خاص بها، والذي سيتم تحميله فقط عند عرض المكون. هذا يعني أنك ستقوم بعمل طلب HTTP واحد لكل كتلة نصية. هل لديك 1000 كتلة نصية في صفحتك؟ → 1000 طلب HTTP إلى خوادمك. وللحد من الضرر وتحسين وقت العرض الأول لتطبيقك، ستحتاج إلى إدخال عدة حدود Suspense أو محملات Skeleton.
93
147
 
94
- ## الفخ: التقييد بالبائع
148
+ > ملاحظة: حتى مع Next.js و SSR، ستظل مكوناتك مروية (hydrated) بعد التحميل، لذا ستظل طلبات HTTP تتم.
95
149
 
96
- هذا ربما يكون أخطر جانب في التدويل المعتمد على المترجم.
150
+ الحل؟ اعتماد حل يسمح بالإعلان عن محتوى محدود النطاق، كما يفعل `i18next`، `next-intl`، أو `intlayer`.
97
151
 
98
- في مكتبة تصريحية، يحتوي كود المصدر الخاص بك على نية صريحة. أنت تملك المفاتيح. إذا قمت بتغيير المكتبة، فقط تغير الاستيراد.
152
+ > ملاحظة: يتطلب `i18next` و `next-intl` منك إدارة استيراد مساحة الأسماء / الرسائل يدويًا لكل صفحة لتحسين حجم الحزمة الخاصة بك. يجب عليك استخدام محلل الحزم مثل `rollup-plugin-visualizer` (vite)، `@next/bundle-analyzer` (next.js)، أو `webpack-bundle-analyzer` (React CRA / Angular / إلخ) لاكتشاف ما إذا كنت تلوث حزمة التطبيق بترجمات غير مستخدمة.
99
153
 
100
- في النهج المعتمد على المترجم، **كود المصدر الخاص بك هو مجرد نص إنجليزي.** "منطق الترجمة" موجود فقط داخل تكوين إضافة البناء.
101
- إذا توقف ذلك المكتبة عن الصيانة، أو إذا تجاوزتها، فأنت عالق. لا يمكنك "الإخراج" بسهولة لأنك لا تملك أي مفاتيح ترجمة في شفرتك المصدرية. سيتعين عليك إعادة كتابة تطبيقك بالكامل يدويًا للانتقال بعيدًا.
154
+ ### العبء على أداء وقت التشغيل
155
+
156
+ لجعل الترجمات تفاعلية (حتى يتم تحديثها فورًا عند تبديل اللغات)، غالبًا ما يقوم المترجم بحقن خطاطيف إدارة الحالة في كل مكون.
157
+
158
+ - **التكلفة:** إذا قمت بعرض قائمة تحتوي على 5000 عنصر، فأنت تقوم بتهيئة 5000 خطاف `useState` و `useEffect` فقط للنصوص. يجب على React التعرف على جميع المستهلكين الخمسة آلاف وإعادة عرضهم في نفس الوقت. هذا يسبب حظرًا كبيرًا في "الخيط الرئيسي"، مما يؤدي إلى تجميد واجهة المستخدم أثناء التبديل. هذا يستهلك الذاكرة ودورات وحدة المعالجة المركزية التي توفرها المكتبات التصريحية (التي تستخدم عادة مزود Context واحد).
159
+
160
+ > لاحظ أن المشكلة مشابهة في أطر عمل أخرى غير React.
161
+
162
+ ## الفخ: القفل مع البائع
163
+
164
+ كن حذرًا عند اختيار حل i18n يسمح باستخراج أو ترحيل مفاتيح الترجمة.
165
+
166
+ في حالة استخدام مكتبة تصريحية، يحتوي كود المصدر الخاص بك صراحةً على نية الترجمة الخاصة بك: هذه هي المفاتيح الخاصة بك، وأنت تتحكم بها. إذا أردت تغيير المكتبات، فعادةً ما تحتاج فقط إلى تحديث الاستيراد.
167
+
168
+ مع نهج المترجم، قد يكون كود المصدر الخاص بك مجرد نص إنجليزي عادي، بدون أي أثر لمنطق الترجمة: كل شيء مخفي في تكوين أداة البناء. إذا أصبح ذلك المكون الإضافي غير مدعوم أو أردت تغيير الحلول، قد تجد نفسك عالقًا. لا توجد طريقة سهلة لـ "الإخراج": لا توجد مفاتيح قابلة للاستخدام في كودك، وقد تحتاج إلى إعادة توليد جميع ترجماتك لمكتبة جديدة.
169
+
170
+ بعض الحلول تقدم أيضًا خدمات توليد الترجمة. لا مزيد من الرصيد؟ لا مزيد من الترجمات.
171
+
172
+ يقوم المترجمون غالبًا بتجزئة النص (على سبيل المثال، `"Hello World"` -> `x7f2a`). تبدو ملفات الترجمة الخاصة بك مثل `{ "x7f2a": "Hola Mundo" }`. الفخ: إذا قمت بتغيير المكتبات، فإن المكتبة الجديدة ترى `"Hello World"` وتبحث عن هذا المفتاح. لن تجده لأن ملف الترجمة الخاص بك مليء بالتجزئات (`x7f2a`).
173
+
174
+ ### القفل على المنصة
175
+
176
+ من خلال اختيار نهج قائم على المترجم، تقيد نفسك بالمنصة الأساسية. على سبيل المثال، بعض المترجمين غير متاحين لجميع أدوات الحزم (مثل Vite أو Turbopack أو Metro). يمكن أن يجعل هذا عمليات النقل المستقبلية صعبة، وقد تحتاج إلى اعتماد حلول متعددة لتغطية جميع تطبيقاتك.
102
177
 
103
178
  ## الجانب الآخر: مخاطر النهج التصريحي
104
179
 
105
- لكي نكون منصفين، الطريقة التصريحية التقليدية ليست مثالية أيضًا. لديها مجموعة من "المشاكل الذاتية".
180
+ للنزاهة، الطريقة التصريحية التقليدية ليست مثالية أيضًا. لديها مجموعة من "الأخطاء الشائعة".
106
181
 
107
- 1. **جحيم المساحات الاسمية:** غالبًا ما يتعين عليك إدارة ملفات JSON التي يجب تحميلها يدويًا (`common.json`، `dashboard.json`، `footer.json`). إذا نسيت واحدًا، سيرى المستخدم المفاتيح الخام.
108
- 2. **التحميل الزائد:** بدون تكوين دقيق، من السهل جدًا تحميل _جميع_ مفاتيح الترجمة الخاصة بك لـ _جميع_ الصفحات عند التحميل الأولي، مما يزيد من حجم الحزمة.
182
+ 1. **جحيم المساحات الاسمية:** غالبًا ما يتعين عليك إدارة ملفات JSON التي يجب تحميلها يدويًا (`common.json`، `dashboard.json`، `footer.json`). إذا نسيت واحدًا، يرى المستخدم المفاتيح الخام.
183
+ 2. **التحميل الزائد:** بدون تكوين دقيق، من السهل جدًا تحميل _جميع_ مفاتيح الترجمة الخاصة بك لجميع الصفحات عند التحميل الأولي، مما يؤدي إلى تضخم حجم الحزمة الخاصة بك.
109
184
  3. **انحراف التزامن:** من الشائع أن تبقى المفاتيح في ملف JSON لفترة طويلة بعد حذف المكون الذي يستخدمها. تنمو ملفات الترجمة الخاصة بك بلا حدود، مليئة بـ "مفاتيح الزومبي".
110
185
 
111
- ## الحل الوسط مع Intlayer
186
+ ## الحل الوسيط من Intlayer
112
187
 
113
- هنا تحاول أدوات مثل **Intlayer** الابتكار. يفهم Intlayer أنه بينما المترجمات قوية، فإن السحر الضمني خطير.
188
+ هنا تحاول أدوات مثل **Intlayer** الابتكار. يفهم Intlayer أنه بينما المجمعات قوية، فإن السحر الضمني خطير.
114
189
 
115
- يقدم Intlayer أمرًا فريدًا **`transform`**. بدلاً من القيام بالسحر فقط في خطوة البناء المخفية، يمكنه فعليًا **إعادة كتابة كود المكون الخاص بك**. يقوم بمسح نصك ويستبدله بإعلانات محتوى صريحة في قاعدة الكود الخاصة بك.
190
+ يقدم Intlayer نهجًا مختلطًا، يتيح لك الاستفادة من مزايا كلا النهجين: إدارة المحتوى التصريحية، والمتوافقة أيضًا مع المجمع الخاص به لتوفير وقت التطوير.
191
+
192
+ وحتى إذا لم تستخدم مترجم Intlayer، فإن Intlayer يقدم أمر `transform` (يمكن الوصول إليه أيضًا باستخدام امتداد VSCode). بدلاً من القيام بالسحر فقط في خطوة البناء المخفية، يمكنه فعليًا **إعادة كتابة كود المكون الخاص بك**. يقوم بمسح نصك ويستبدله بإعلانات محتوى صريحة في قاعدة الكود الخاصة بك.
116
193
 
117
194
  هذا يمنحك أفضل ما في العالمين:
118
195
 
119
- 1. **الدقة:** تحتفظ بترجماتك قريبة من مكوناتك (محسنًا التجزئة وإزالة الشجر).
196
+ 1. **الدقة:** تحتفظ بترجماتك قريبة من مكوناتك (مما يحسن من التجزئة وإزالة الشجر غير المستخدم).
120
197
  2. **الأمان:** تصبح الترجمة كودًا صريحًا، وليس سحرًا مخفيًا في وقت البناء.
121
- 3. **عدم القفل:** نظرًا لأن الكود يتم تحويله إلى هيكل إعلاني قياسي داخل مستودعك، فلن تخفي المنطق في إضافة webpack.
198
+ 3. **عدم القفل:** نظرًا لأن الكود يتم تحويله إلى هيكل إعلاني داخل مستودعك، يمكنك بسهولة الضغط على Tab، أو استخدام مساعد IDE الخاص بك (copilot)، لتوليد إعلانات المحتوى الخاصة بك، أنت لا تخفي المنطق في مكون إضافي لـ webpack.
122
199
 
123
200
  ## الخلاصة
124
201
 
125
- فأي منهما يجب أن تختار؟
202
+ فأي خيار يجب أن تختار؟
203
+
204
+ **إذا كنت تبني MVP، أو تريد التحرك بسرعة:**
205
+ النهج المعتمد على المترجم هو خيار صالح. يسمح لك بالتحرك بسرعة كبيرة. لا تحتاج للقلق بشأن هيكل الملفات أو المفاتيح. فقط قم بالبناء. الدين الفني سيكون مشكلة لـ "أنت في المستقبل".
206
+
207
+ **إذا كنت مطورًا مبتدئًا، أو لا تهتم بالتحسين:**
208
+ إذا كنت تريد أقل إدارة يدوية، فمن المحتمل أن يكون النهج المعتمد على المترجم هو الأفضل. لن تحتاج إلى التعامل مع المفاتيح أو ملفات الترجمة بنفسك - فقط اكتب النص، والمترجم يقوم بالباقي تلقائيًا. هذا يقلل من جهد الإعداد والأخطاء الشائعة في التدويل المرتبطة بالخطوات اليدوية.
126
209
 
127
- **إذا كنت مطورًا مبتدئًا، أو مؤسسًا منفردًا، أو تبني MVP:**
128
- النهج القائم على المترجم هو خيار صالح. يسمح لك بالتحرك بسرعة كبيرة. لا تحتاج إلى القلق بشأن هياكل الملفات أو المفاتيح. فقط تبني. الدين الفني هو مشكلة لـ "أنت في المستقبل".
210
+ **إذا كنت تقوم بتدويل مشروع قائم يحتوي بالفعل على آلاف المكونات التي تحتاج لإعادة هيكلة:**
211
+ يمكن أن يكون النهج القائم على المترجم خيارًا عمليًا هنا. يمكن لمرحلة الاستخراج الأولية أن توفر أسابيع أو شهورًا من العمل اليدوي. ومع ذلك، فكر في استخدام أداة مثل أمر `transform` في Intlayer، والتي يمكنها استخراج السلاسل النصية وتحويلها إلى إعلانات محتوى صريحة وتصريحية. هذا يمنحك سرعة الأتمتة مع الحفاظ على أمان وقابلية نقل النهج التصريحي. تحصل على أفضل ما في العالمين: هجرة أولية سريعة دون ديون معمارية طويلة الأمد.
129
212
 
130
- **إذا كنت تبني تطبيقًا احترافيًا على مستوى المؤسسات:**
131
- السحر عادةً ما يكون فكرة سيئة. تحتاج إلى السيطرة.
213
+ **إذا كنت تبني تطبيقًا احترافيًا من الدرجة المؤسسية:**
214
+ السحر عادةً ما يكون فكرة سيئة. أنت بحاجة إلى التحكم.
132
215
 
133
216
  - تحتاج إلى التعامل مع البيانات الديناميكية من الخلفيات.
134
- - تحتاج إلى ضمان الأداء على الأجهزة منخفضة المواصفات (تجنب انفجارات الـ hooks).
217
+ - تحتاج إلى ضمان الأداء على الأجهزة منخفضة المواصفات (تجنب انفجارات الـ hook).
135
218
  - تحتاج إلى التأكد من أنك لست مقيدًا بأداة بناء معينة إلى الأبد.
136
219
 
137
- بالنسبة للتطبيقات الاحترافية، يظل **إدارة المحتوى التصريحية** (مثل Intlayer أو المكتبات المعروفة) المعيار الذهبي. فهي تفصل بين اهتماماتك، وتحافظ على نظافة هيكلك، وتضمن أن قدرة تطبيقك على التحدث بعدة لغات لا تعتمد على "صندوق أسود" يقوم المترجم بتخمين نواياك.
220
+ بالنسبة للتطبيقات المهنية، تظل **إدارة المحتوى التصريحية** (مثل Intlayer أو المكتبات المعروفة) هي المعيار الذهبي. فهي تفصل بين اهتماماتك، وتحافظ على نظافة هيكلك المعماري، وتضمن أن قدرة تطبيقك على التحدث بعدة لغات لا تعتمد على "صندوق أسود" يقوم المترجم بتخمين نواياك.
@@ -2,7 +2,7 @@
2
2
  createdAt: 2025-11-24
3
3
  updatedAt: 2025-11-24
4
4
  title: Compiler vs. deklarative i18n
5
- description: Untersuchung der architektonischen Kompromisse zwischen "magischer" compiler-basierter Internationalisierung und explizitem deklarativem Content-Management.
5
+ description: Untersuchung der architektonischen Kompromisse zwischen "magischer" compilerbasierter Internationalisierung und explizitem deklarativem Content-Management.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - Internationalisierung
@@ -18,27 +18,59 @@ slugs:
18
18
  - compiler-vs-declarative-i18n
19
19
  ---
20
20
 
21
- # Pro und Contra compiler-basierte i18n
21
+ # Pro und Contra compilerbasierte i18n
22
22
 
23
- Wenn Sie seit mehr als einem Jahrzehnt Webanwendungen entwickeln, wissen Sie, dass Internationalisierung (i18n) schon immer ein Reibungspunkt war. Es ist oft die Aufgabe, die niemand machen möchte – Strings extrahieren, JSON-Dateien verwalten und sich um Pluralisierungsregeln kümmern.
23
+ Wenn Sie seit mehr als einem Jahrzehnt Webanwendungen entwickeln, wissen Sie, dass Internationalisierung (i18n) schon immer ein Reibungspunkt war. Es ist oft die Aufgabe, die niemand machen möchte – das Extrahieren von Strings, das Verwalten von JSON-Dateien und das Sorgen um Pluralisierungsregeln.
24
24
 
25
- In letzter Zeit ist eine neue Welle von "compiler-basierten" i18n-Tools aufgetaucht, die versprechen, diesen Schmerz verschwinden zu lassen. Das Versprechen ist verlockend: **Schreiben Sie einfach den Text in Ihre Komponenten, und lassen Sie das Build-Tool den Rest erledigen.** Keine Keys, keine Importe, einfach Magie.
25
+ Kürzlich ist eine neue Welle von **"compilerbasierten" i18n-Tools** aufgetaucht, die versprechen, diesen Schmerz verschwinden zu lassen. Das Versprechen ist verlockend: **Schreiben Sie einfach den Text in Ihre Komponenten, und lassen Sie das Build-Tool den Rest erledigen.** Keine Schlüssel, keine Importe, einfach Magie.
26
26
 
27
27
  Aber wie bei allen Abstraktionen in der Softwareentwicklung hat Magie ihren Preis.
28
28
 
29
- In diesem Blogbeitrag werden wir den Wandel von deklarativen Bibliotheken hin zu compiler-basierten Ansätzen untersuchen, die versteckten architektonischen Schulden, die sie mit sich bringen, und warum der "langweilige" Weg für professionelle Anwendungen immer noch der beste sein könnte.
29
+ In diesem Blogbeitrag werden wir den Wandel von deklarativen Bibliotheken hin zu compilerbasierten Ansätzen untersuchen, die versteckten architektonischen Schulden, die sie mit sich bringen, und warum der langweilige" Weg für professionelle Anwendungen vielleicht immer noch der beste ist.
30
30
 
31
- ## Eine kurze Geschichte der Übersetzung
31
+ ## Inhaltsverzeichnis
32
+
33
+ <TOC/>
34
+
35
+ ## Eine kurze Geschichte der Internationalisierung
32
36
 
33
37
  Um zu verstehen, wo wir stehen, müssen wir zurückblicken, wo wir angefangen haben.
34
38
 
35
39
  Um 2011–2012 sah die JavaScript-Landschaft ganz anders aus. Bundler, wie wir sie heute kennen (Webpack, Vite), existierten entweder noch nicht oder steckten noch in den Kinderschuhen. Wir klebten Skripte direkt im Browser zusammen. In dieser Zeit entstanden Bibliotheken wie **i18next**.
36
40
 
37
- Sie lösten das Problem auf die damals einzig mögliche Weise: **Runtime-Wörterbücher**. Man lud ein riesiges JSON-Objekt in den Speicher, und eine Funktion suchte die Schlüssel zur Laufzeit nach. Es war zuverlässig, explizit und funktionierte überall.
41
+ Sie lösten das Problem auf die damals einzig mögliche Weise: **Laufzeit-Wörterbücher**. Man lud ein riesiges JSON-Objekt in den Speicher, und eine Funktion suchte die Schlüssel zur Laufzeit nach. Es war zuverlässig, explizit und funktionierte überall.
42
+
43
+ Schneller Vorlauf bis heute. Wir haben leistungsstarke Compiler (SWC, Rust-basierte Bundler), die Abstract Syntax Trees (AST) in Millisekunden parsen können. Diese Leistung brachte eine neue Idee hervor: _Warum verwalten wir Schlüssel manuell? Warum kann der Compiler nicht einfach den Text "Hello World" sehen und für uns austauschen?_
44
+
45
+ So wurde die compilerbasierte i18n geboren.
46
+
47
+ > **Beispiel für compiler-basierte i18n:**
48
+ >
49
+ > - Paraglide (Tree-shaken-Module, die jede Nachricht in eine kleine ESM-Funktion kompilieren, sodass Bundler ungenutzte Sprachen und Schlüssel automatisch entfernen können. Du importierst Nachrichten als Funktionen, anstatt String-Schlüssel nachzuschlagen.)
50
+ > - LinguiJS (Macro-zu-Funktion-Compiler, der Nachrichten-Makros wie `<Trans>` zur Build-Zeit in einfache JS-Funktionsaufrufe umschreibt. Du erhältst ICU/MessageFormat-Syntax mit einem sehr kleinen Laufzeit-Footprint.)
51
+ > - Lingo.dev (Konzentriert sich auf die Automatisierung der Lokalisierungspipeline, indem übersetzte Inhalte direkt während des Builds deiner React-Anwendung injiziert werden. Es kann Übersetzungen mithilfe von KI automatisch generieren und sich direkt in CI/CD integrieren.)
52
+ > - Wuchale (Svelte-first Preprocessor, der Inline-Text in .svelte-Dateien extrahiert und in Wrapper-freie Übersetzungsfunktionen kompiliert. Er vermeidet String-Schlüssel und trennt die Logik der Inhaltsextraktion vollständig vom Hauptanwendungs-Laufzeitumfeld.)
53
+ > - Intlayer (Compiler / Extract CLI, der deine Komponenten parst, typisierte Wörterbücher generiert und optional den Code umschreiben kann, um expliziten Intlayer-Inhalt zu verwenden. Das Ziel ist es, den Compiler für Geschwindigkeit zu nutzen und gleichzeitig einen deklarativen, framework-agnostischen Kern beizubehalten.)
54
+
55
+ > **Beispiel für deklarative i18n:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (Der ausgereifte Industriestandard, der zur Laufzeit JSON-Wörterbücher und ein umfangreiches Plugin-Ökosystem verwendet)
58
+ > - react-intl (Teil der FormatJS-Bibliothek, die sich auf die standardisierte ICU-Nachrichtensyntax und strikte Datenformatierung konzentriert)
59
+ > - next-intl (Speziell für Next.js optimiert mit Integration für den App Router und React Server Components)
60
+ > - vue-i18n / @nuxt/i18n (Die Standardlösung im Vue-Ökosystem, die Übersetzungsblöcke auf Komponentenebene und eine enge Reaktivitätsintegration bietet)
61
+ > - svelte-i18n (Ein leichter Wrapper um Svelte Stores für reaktive, zur Laufzeit stattfindende Übersetzungen)
62
+ > - angular-translate (Die veraltete dynamische Übersetzungsbibliothek, die auf Laufzeit-Schlüsselabfragen statt auf Build-Zeit-Zusammenführung setzt)
63
+ > - angular-i18n (Angulards native Ahead-of-Time-Methode, die XLIFF-Dateien direkt während des Builds in Templates zusammenführt)
64
+ > - Tolgee (Kombiniert deklarativen Code mit einem In-Context-SDK für „Click-to-Translate“-Bearbeitung direkt in der UI)
65
+ > - Intlayer (Komponentenbasierter Ansatz, der Content-Declaration-Dateien verwendet und so natives Tree-Shaking sowie TypeScript-Validierung ermöglicht)
66
+
67
+ ## Der Intlayer Compiler
68
+
69
+ Obwohl **Intlayer** eine Lösung ist, die grundsätzlich einen **deklarativen Ansatz** für Ihre Inhalte fördert, beinhaltet sie einen Compiler, der die Entwicklung beschleunigen oder schnelles Prototyping erleichtern soll.
38
70
 
39
- Spulen wir bis heute vor. Wir haben leistungsstarke Compiler (SWC, Rust-basierte Bundler), die Abstract Syntax Trees (AST) in Millisekunden parsen können. Diese Leistung brachte eine neue Idee hervor: _Warum verwalten wir Schlüssel manuell? Warum kann der Compiler nicht einfach den Text "Hello World" sehen und für uns austauschen?_
71
+ Der Intlayer Compiler durchläuft den AST (Abstract Syntax Tree) Ihrer React-, Vue- oder Svelte-Komponenten sowie anderer JavaScript/TypeScript-Dateien. Seine Aufgabe ist es, hartkodierte Strings zu erkennen und in dedizierte `.content`-Deklarationen zu extrahieren.
40
72
 
41
- So wurde das compiler-basierte i18n geboren.
73
+ > Für weitere Details siehe die Dokumentation: [Intlayer Compiler Docs](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/compiler.md)
42
74
 
43
75
  ## Der Reiz des Compilers (Der "Magische" Ansatz)
44
76
 
@@ -46,92 +78,143 @@ Es gibt einen Grund, warum dieser neue Ansatz im Trend liegt. Für einen Entwick
46
78
 
47
79
  ### 1. Geschwindigkeit und "Flow"
48
80
 
49
- Wenn man im Flow ist, unterbricht das Nachdenken über einen Variablennamen (`home_hero_title_v2`) den Arbeitsfluss. Mit einem Compiler-Ansatz tippt man einfach `<p>Welcome back</p>` und macht weiter. Die Reibung ist null.
81
+ Wenn man im Flow ist, unterbricht das Nachdenken über einen semantischen Variablennamen (`home_hero_title_v2`) den Arbeitsfluss. Mit einem Compiler-Ansatz tippt man einfach `<p>Welcome back</p>` und macht weiter. Die Reibung ist null.
50
82
 
51
- ### 2. Die Rettungsmission für Altbestände
83
+ ### 2. Die Rettungsmission für Legacy-Code
52
84
 
53
- Stellen Sie sich vor, Sie erben eine riesige Codebasis mit 5.000 Komponenten und null Übersetzungen. Diese manuell mit einem schlüsselbasierten System nachzurüsten, ist ein monatelanger Albtraum. Ein compilerbasiertes Tool fungiert als Rettungsstrategie, indem es sofort Tausende von Strings extrahiert, ohne dass Sie eine einzige Datei manuell anfassen müssen.
85
+ Stellen Sie sich vor, Sie erben eine riesige Codebasis mit 5.000 Komponenten und keinen Übersetzungen. Diese nachträglich mit einem manuellen schlüsselbasierten System auszustatten, ist ein monatelanger Albtraum. Ein compilerbasiertes Tool fungiert als Rettungsstrategie, indem es sofort Tausende von Strings extrahiert, ohne dass Sie eine einzige Datei manuell anfassen müssen.
54
86
 
55
87
  ### 3. Das KI-Zeitalter
56
88
 
57
- Dies ist ein moderner Vorteil, den wir nicht übersehen sollten. KI-Coding-Assistenten (wie Copilot oder ChatGPT) erzeugen natürlicherweise standardmäßiges JSX/HTML. Sie kennen Ihr spezifisches Übersetzungsschlüsselschema nicht.
89
+ Dies ist ein moderner Vorteil, den wir nicht übersehen sollten. KI-Coding-Assistenten (wie Copilot oder ChatGPT) erzeugen natürlich standardmäßiges JSX/HTML. Sie kennen Ihr spezifisches Übersetzungsschlüsselschema nicht.
58
90
 
59
91
  - **Deklarativ:** Sie müssen die Ausgabe der KI umschreiben, um Text durch Schlüssel zu ersetzen.
60
- - **Compiler:** Sie kopieren den Code der KI einfach und es funktioniert sofort.
92
+ - **Compiler:** Sie kopieren den Code der KI und es funktioniert einfach.
61
93
 
62
- ## Die Realität: Warum "Magie" gefährlich ist
94
+ ## Der Realitätscheck: Warum Magie gefährlich ist
63
95
 
64
- Obwohl die "Magie" verlockend ist, gibt es Undichtigkeiten in der Abstraktion. Sich auf ein Build-Tool zu verlassen, das menschliche Absichten versteht, führt zu architektonischer Fragilität.
96
+ Während die Magie verlockend ist, treten Abstraktionslecks auf. Sich darauf zu verlassen, dass ein Build-Tool die menschliche Absicht versteht, führt zu architektonischer Fragilität.
65
97
 
66
- ### 1. Heuristische Fragilität (Das Ratespiel)
98
+ ### Heuristische Fragilität (Das Ratespiel)
67
99
 
68
- Der Compiler muss erraten, was Inhalt und was Code ist.
100
+ Der Compiler muss erraten, was Inhalt und was Code ist. Das führt zu Randfällen, bei denen man am Ende gegen das Tool „kämpft“.
69
101
 
70
- - Wird `className="active"` übersetzt? Es ist ein String.
71
- - Wird `status="pending"` übersetzt?
72
- - Wird `<MyComponent errorMessage="An error occurred" />` übersetzt?
73
- - Wird eine Produkt-ID wie `"AX-99"` übersetzt?
102
+ Betrachten Sie diese Szenarien:
74
103
 
75
- Sie enden unweigerlich damit, gegen den Compiler "anzukämpfen" und fügen spezifische Kommentare hinzu (wie `// ignore-translation`), um zu verhindern, dass er Ihre Anwendungslogik bricht.
104
+ - Wird `<span className="active"></span>` extrahiert? (Es ist ein String, aber wahrscheinlich eine Klasse).
105
+ - Wird `<span status="pending"></span>` extrahiert? (Es ist ein Prop-Wert).
106
+ - Wird `<span>{"Hello World"}</span>` extrahiert? (Es ist ein JS-Ausdruck).
107
+ - Wird `<span>Hello {name}. How are you?</span>` extrahiert? (Interpolation ist komplex).
108
+ - Wird `<span aria-label="Image of cat"></span>` extrahiert? (Barrierefreiheitsattribute müssen übersetzt werden).
109
+ - Wird `<span data-testid="my-element"></span>` extrahiert? (Test-IDs sollten NICHT übersetzt werden).
110
+ - Wird `<MyComponent errorMessage="An error occurred" />` extrahiert?
111
+ - Wird `<p>This is a paragraph{" "}\n containing multiple lines</p>` extrahiert?
112
+ - Wird das Ergebnis der Funktion `<p>{getStatusMessage()}</p>` extrahiert?
113
+ - Wird `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>` extrahiert?
114
+ - Wird eine Produkt-ID wie `<span>AX-99</span>` extrahiert?
76
115
 
77
- ### 2. Die harte Grenze bei dynamischen Daten
116
+ Unweigerlich fügen Sie spezifische Kommentare hinzu (wie `// ignore-translation` oder spezifische Props wie `data-compiler-ignore="true"`), um zu verhindern, dass die Anwendung logik bricht.
117
+
118
+ ### Wie geht Intlayer mit dieser Komplexität um?
119
+
120
+ Intlayer verwendet einen gemischten Ansatz, um zu erkennen, ob ein Feld für die Übersetzung extrahiert werden soll, und versucht dabei, Fehlalarme zu minimieren:
121
+
122
+ 1. **AST-Analyse:** Es überprüft den Elementtyp (z. B. Unterscheidung zwischen einem `reactNode`, einem `label` oder einer `title`-Prop).
123
+ 2. **Mustererkennung:** Es erkennt, ob der String großgeschrieben ist oder Leerzeichen enthält, was darauf hindeutet, dass es sich wahrscheinlich um menschenlesbaren Text und nicht um einen Codebezeichner handelt.
124
+
125
+ ### Die harte Grenze für dynamische Daten
78
126
 
79
127
  Die Compiler-Extraktion basiert auf **statischer Analyse**. Sie muss den Literalstring in Ihrem Code sehen, um eine stabile ID zu generieren.
80
- Wenn Ihre API einen Fehlercode-String wie `server_error` zurückgibt, können Sie ihn nicht mit einem Compiler übersetzen, da der Compiler diesen String zur Build-Zeit nicht kennt. Sie sind gezwungen, ein sekundäres "nur zur Laufzeit" System nur für dynamische Daten zu erstellen.
128
+ Wenn Ihre API einen Fehlercode-String wie `server_error` zurückgibt, können Sie diesen nicht mit einem Compiler übersetzen, da der Compiler zur Build-Zeit nicht weiß, dass dieser String existiert. Sie sind gezwungen, ein sekundäres "Nur-Laufzeit"-System ausschließlich für dynamische Daten zu erstellen.
129
+
130
+ ### Fehlende Chunk-Aufteilung
131
+
132
+ Bestimmte Compiler teilen Übersetzungen nicht pro Seite auf. Wenn Ihr Compiler eine große JSON-Datei pro Sprache generiert (z. B. `./lang/en.json`, `./lang/fr.json` usw.), laden Sie wahrscheinlich Inhalte aller Seiten für eine einzelne besuchte Seite. Außerdem wird jede Komponente, die Ihre Inhalte verwendet, wahrscheinlich mit weit mehr Inhalt als nötig hydriert, was potenziell zu Performance-Problemen führen kann.
133
+
134
+ Seien Sie auch vorsichtig beim dynamischen Laden Ihrer Übersetzungen. Wenn dies nicht gemacht wird, laden Sie Inhalte für alle Sprachen zusätzlich zur aktuellen.
81
135
 
82
- ### 3. "Chunk-Explosion" und Netzwerk-Wasserfälle
136
+ > Um das Problem zu veranschaulichen, betrachten Sie eine Website mit 10 Seiten und 10 Sprachen (alle zu 100 % einzigartig). Sie würden Inhalte für 99 zusätzliche Seiten laden (10 × 10 - 1).
83
137
 
84
- Um Tree-Shaking zu ermöglichen, teilen Compiler-Tools Übersetzungen oft pro Komponente auf.
138
+ ### „Chunk-Explosion“ und Netzwerk-Wasserfälle
85
139
 
86
- - **Die Folge:** Eine einzelne Seitenansicht mit 50 kleinen Komponenten könnte **50 separate HTTP-Anfragen** für winzige Übersetzungsfragmente auslösen. Selbst mit HTTP/2 erzeugt dies eine Netzwerk-Wasserfallstruktur, die Ihre Anwendung im Vergleich zum Laden eines einzigen, optimierten Sprachpakets träge erscheinen lässt.
140
+ Um das Chunking-Problem zu lösen, bieten einige Lösungen Chunking pro Komponente oder sogar pro Schlüssel an. Doch das Problem wird nur teilweise gelöst. Das Verkaufsargument für diese Lösungen ist oft: „Ihr Inhalt wird tree-shaken.“
87
141
 
88
- ### 4. Laufzeit-Performance-Overhead
142
+ Tatsächlich, wenn Sie Inhalte statisch laden, wird Ihre Lösung ungenutzte Inhalte tree-shaken, aber Sie werden dennoch Inhalte aus allen Sprachen mit Ihrer Anwendung laden.
89
143
 
90
- Um Übersetzungen reaktiv zu machen (damit sie sich sofort aktualisieren, wenn Sie die Sprache wechseln), injiziert der Compiler häufig Zustandsverwaltungs-Hooks in _jede_ Komponente.
144
+ Warum also nicht dynamisch laden? Ja, in diesem Fall laden Sie mehr als den notwendigen Inhalt, aber das ist nicht ohne Kompromisse.
91
145
 
92
- - **Die Kosten:** Wenn Sie eine Liste mit 5.000 Elementen rendern, initialisieren Sie 5.000 `useState`- und `useEffect`-Hooks ausschließlich für Text. Dies verbraucht Speicher und CPU-Zyklen, die deklarative Bibliotheken (die typischerweise einen einzigen Context-Provider verwenden) einsparen.
146
+ Das dynamische Laden von Inhalten isoliert jeden Inhaltsblock in einem eigenen Chunk, der nur geladen wird, wenn die Komponente gerendert wird. Das bedeutet, dass Sie für jeden Textblock eine HTTP-Anfrage stellen. 1.000 Textblöcke auf Ihrer Seite? 1.000 HTTP-Anfragen an Ihre Server. Und um den Schaden zu begrenzen und die erste Renderzeit Ihrer Anwendung zu optimieren, müssen Sie mehrere Suspense-Grenzen oder Skeleton Loader einfügen.
147
+
148
+ > Hinweis: Selbst mit Next.js und SSR werden Ihre Komponenten nach dem Laden noch hydriert, sodass die HTTP-Anfragen weiterhin ausgeführt werden.
149
+
150
+ Die Lösung? Die Einführung einer Lösung, die es ermöglicht, scoped Content-Deklarationen zu definieren, wie es `i18next`, `next-intl` oder `intlayer` tun.
151
+
152
+ > Hinweis: `i18next` und `next-intl` erfordern, dass Sie Ihre Namespace- / Nachrichtenimporte manuell für jede Seite verwalten, um die Bundle-Größe zu optimieren. Sie sollten einen Bundle-Analyzer wie `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js) oder `webpack-bundle-analyzer` (React CRA / Angular / etc.) verwenden, um zu erkennen, ob Sie Ihr Bundle mit ungenutzten Übersetzungen belasten.
153
+
154
+ ### Laufzeit-Performance-Overhead
155
+
156
+ Um Übersetzungen reaktiv zu machen (damit sie sofort aktualisiert werden, wenn Sie die Sprache wechseln), injiziert der Compiler häufig State-Management-Hooks in jede Komponente.
157
+
158
+ - **Die Kosten:** Wenn Sie eine Liste mit 5.000 Elementen rendern, initialisieren Sie 5.000 `useState`- und `useEffect`-Hooks ausschließlich für den Text. React muss alle 5.000 Verbraucher gleichzeitig identifizieren und neu rendern. Dies verursacht eine massive Blockade des "Main Thread" und friert die Benutzeroberfläche während des Wechsels ein. Dies verbraucht Speicher und CPU-Zyklen, die deklarative Bibliotheken (die typischerweise einen einzigen Context-Provider verwenden) einsparen.
159
+
160
+ > Beachten Sie, dass das Problem bei anderen Frameworks als React ähnlich ist.
93
161
 
94
162
  ## Die Falle: Vendor Lock-in
95
163
 
96
- Dies ist wohl der gefährlichste Aspekt von compiler-basierter i18n.
164
+ Seien Sie vorsichtig bei der Wahl einer i18n-Lösung, die die Extraktion oder Migration von Übersetzungsschlüsseln ermöglicht.
97
165
 
98
- In einer deklarativen Bibliothek enthält Ihr Quellcode eine explizite Absicht. Sie besitzen die Keys. Wenn Sie die Bibliothek wechseln, ändern Sie einfach den Import.
166
+ Im Fall einer deklarativen Bibliothek enthält Ihr Quellcode explizit Ihre Übersetzungsabsicht: Dies sind Ihre Schlüssel, und Sie kontrollieren sie. Wenn Sie die Bibliothek wechseln möchten, müssen Sie in der Regel nur den Import aktualisieren.
99
167
 
100
- In einem compiler-basierten Ansatz ist **Ihr Quellcode nur englischer Text.** Die „Übersetzungslogik“ existiert nur in der Konfiguration des Build-Plugins.
101
- Wenn diese Bibliothek nicht mehr gepflegt wird oder wenn Sie darüber hinauswachsen, sind Sie festgefahren. Sie können nicht einfach „aussteigen“, weil Sie keine Übersetzungsschlüssel in Ihrem Quellcode haben. Sie müssten Ihre gesamte Anwendung manuell neu schreiben, um zu migrieren.
168
+ Bei einem Compiler-Ansatz besteht Ihr Quellcode möglicherweise nur aus einfachem englischem Text, ohne jegliche Übersetzungslogik: Alles ist in der Build-Tool-Konfiguration verborgen. Wenn dieses Plugin nicht mehr gepflegt wird oder Sie die Lösung wechseln möchten, könnten Sie feststecken. Es gibt keinen einfachen Weg zum „Aussteigen“: Es gibt keine verwendbaren Schlüssel in Ihrem Code, und Sie müssen möglicherweise alle Ihre Übersetzungen für eine neue Bibliothek neu generieren.
169
+
170
+ Einige Lösungen bieten auch Übersetzungsgenerierungsdienste an. Keine Credits mehr? Keine Übersetzungen mehr.
171
+
172
+ Compiler hashen oft den Text (z. B. `"Hello World"` -> `x7f2a`). Ihre Übersetzungsdateien sehen dann so aus: `{ "x7f2a": "Hola Mundo" }`. Die Falle: Wenn Sie die Bibliothek wechseln, sieht die neue Bibliothek `"Hello World"` und sucht nach diesem Schlüssel. Sie wird ihn nicht finden, weil Ihre Übersetzungsdatei voller Hashes (`x7f2a`) ist.
173
+
174
+ ### Plattform-Abhängigkeit
175
+
176
+ Durch die Wahl eines compiler-basierten Ansatzes binden Sie sich an die zugrunde liegende Plattform. Beispielsweise sind bestimmte Compiler nicht für alle Bundler verfügbar (wie Vite, Turbopack oder Metro). Dies kann zukünftige Migrationen erschweren, und Sie müssen möglicherweise mehrere Lösungen einführen, um alle Ihre Anwendungen abzudecken.
102
177
 
103
178
  ## Die andere Seite: Risiken des deklarativen Ansatzes
104
179
 
105
- Um fair zu sein, ist der traditionelle deklarative Weg auch nicht perfekt. Er hat seine eigenen „Fußangeln“.
180
+ Um fair zu sein, ist der traditionelle deklarative Weg auch nicht perfekt. Er hat seine eigenen "Fallstricke".
106
181
 
107
182
  1. **Namespace-Hölle:** Sie müssen oft manuell verwalten, welche JSON-Dateien geladen werden (`common.json`, `dashboard.json`, `footer.json`). Wenn Sie eine vergessen, sieht der Benutzer rohe Schlüssel.
108
- 2. **Übermäßiges Laden:** Ohne sorgfältige Konfiguration ist es sehr einfach, versehentlich _alle_ Ihre Übersetzungsschlüssel für _alle_ Seiten beim ersten Laden zu laden, was Ihre Bundle-Größe aufbläht.
109
- 3. **Synchronisationsabweichung:** Es ist üblich, dass Schlüssel lange nach der Löschung der sie verwendenden Komponente in der JSON-Datei verbleiben. Ihre Übersetzungsdateien wachsen unendlich und sind mit Zombie-Schlüsseln gefüllt.
183
+ 2. **Übermäßiges Laden:** Ohne sorgfältige Konfiguration ist es sehr einfach, versehentlich _alle_ Ihre Übersetzungsschlüssel für _alle_ Seiten beim ersten Laden zu laden, was die Bundle-Größe aufbläht.
184
+ 3. **Synchronisationsabweichung:** Es ist üblich, dass Schlüssel lange nach der Löschung der sie verwendenden Komponente in der JSON-Datei verbleiben. Ihre Übersetzungsdateien wachsen unendlich und sind mit "Zombie-Schlüsseln" gefüllt.
110
185
 
111
- ## Der Mittelweg mit Intlayer
186
+ ## Der Mittelweg von Intlayer
112
187
 
113
188
  Hier versuchen Werkzeuge wie **Intlayer** zu innovieren. Intlayer versteht, dass Compiler zwar mächtig sind, implizite Magie jedoch gefährlich ist.
114
189
 
115
- Intlayer bietet einen einzigartigen **`transform`-Befehl** an. Anstatt nur Magie im versteckten Build-Schritt auszuführen, kann es tatsächlich **Ihren Komponenten-Code umschreiben**. Es scannt Ihren Text und ersetzt ihn durch explizite Inhaltsdeklarationen in Ihrem Codebase.
190
+ Intlayer bietet einen gemischten Ansatz, der es Ihnen ermöglicht, von den Vorteilen beider Ansätze zu profitieren: deklaratives Content-Management, das auch mit seinem Compiler kompatibel ist, um Entwicklungszeit zu sparen.
116
191
 
117
- Das bietet Ihnen das Beste aus beiden Welten:
192
+ Und selbst wenn Sie den Intlayer-Compiler nicht verwenden, bietet Intlayer einen `transform`-Befehl an (auch über die VSCode-Erweiterung zugänglich). Anstatt nur Magie im versteckten Build-Schritt auszuführen, kann er tatsächlich **Ihren Komponenten-Code umschreiben**. Er durchsucht Ihren Text und ersetzt ihn durch explizite Inhaltsdeklarationen in Ihrem Code-Repository.
193
+
194
+ Das gibt Ihnen das Beste aus beiden Welten:
118
195
 
119
196
  1. **Granularität:** Sie halten Ihre Übersetzungen nah an Ihren Komponenten (verbessert Modularität und Tree-Shaking).
120
197
  2. **Sicherheit:** Die Übersetzung wird zu explizitem Code, nicht zu versteckter Build-Zeit-Magie.
121
- 3. **Keine Bindung:** Da der Code in eine standardisierte deklarative Struktur innerhalb Ihres Repositories umgewandelt wird, verstecken Sie keine Logik in einem Webpack-Plugin.
198
+ 3. **Keine Abhängigkeit:** Da der Code in eine deklarative Struktur innerhalb Ihres Repos umgewandelt wird, können Sie einfach Tab drücken oder den Copilot Ihres IDEs verwenden, um Ihre Inhaltsdeklarationen zu generieren; Sie verstecken keine Logik in einem Webpack-Plugin.
122
199
 
123
200
  ## Fazit
124
201
 
125
- Welche Methode sollten Sie also wählen?
202
+ Welche Option sollten Sie also wählen?
203
+
204
+ **Wenn Sie ein MVP erstellen oder schnell vorankommen möchten:**
205
+ Der compiler-basierte Ansatz ist eine gültige Wahl. Er ermöglicht es Ihnen, unglaublich schnell zu arbeiten. Sie müssen sich nicht um Dateistrukturen oder Schlüssel kümmern. Sie bauen einfach. Die technische Schuld ist ein Problem für das „zukünftige Ich“.
206
+
207
+ **Wenn Sie ein Junior-Entwickler sind oder sich nicht um Optimierung kümmern:**
208
+ Wenn Sie die geringste manuelle Verwaltung wünschen, ist ein compiler-basierter Ansatz wahrscheinlich am besten. Sie müssen sich nicht selbst um Schlüssel oder Übersetzungsdateien kümmern – schreiben Sie einfach Text, und der Compiler automatisiert den Rest. Dies reduziert den Einrichtungsaufwand und häufige i18n-Fehler, die mit manuellen Schritten verbunden sind.
126
209
 
127
- **Wenn Sie ein Junior-Entwickler, ein Solo-Gründer oder ein MVP-Ersteller sind:**
128
- Der compilerbasierte Ansatz ist eine gültige Wahl. Er ermöglicht es Ihnen, unglaublich schnell voranzukommen. Sie müssen sich nicht um Dateistrukturen oder Schlüssel kümmern. Sie bauen einfach. Die technische Schuld ist ein Problem für das „zukünftige Sie“.
210
+ **Wenn Sie ein bestehendes Projekt internationalisieren, das bereits Tausende von Komponenten zur Überarbeitung enthält:**
211
+ Ein compiler-basierter Ansatz kann hier eine pragmatische Wahl sein. Die anfängliche Extraktionsphase kann Wochen oder Monate manueller Arbeit einsparen. Erwägen Sie jedoch die Verwendung eines Tools wie den `transform`-Befehl von Intlayer, der Zeichenketten extrahieren und in explizite deklarative Inhaltsdeklarationen umwandeln kann. Dies bietet Ihnen die Geschwindigkeit der Automatisierung bei gleichzeitiger Sicherheit und Portabilität eines deklarativen Ansatzes. Sie erhalten das Beste aus beiden Welten: eine schnelle anfängliche Migration ohne langfristige architektonische Schulden.
129
212
 
130
- **Wenn Sie eine professionelle, unternehmensgerechte Anwendung entwickeln:**
131
- Magie ist im Allgemeinen eine schlechte Idee. Sie brauchen Kontrolle.
213
+ **Wenn Sie eine professionelle, unternehmensgerechte Anwendung entwickeln:**
214
+ Magie ist im Allgemeinen keine gute Idee. Sie benötigen Kontrolle.
132
215
 
133
216
  - Sie müssen dynamische Daten von Backends verarbeiten.
134
217
  - Sie müssen die Leistung auf Geräten mit geringer Leistung sicherstellen (Vermeidung von Hook-Explosionen).
135
218
  - Sie müssen sicherstellen, dass Sie nicht für immer an ein bestimmtes Build-Tool gebunden sind.
136
219
 
137
- Für professionelle Anwendungen bleibt **Deklaratives Content Management** (wie Intlayer oder etablierte Bibliotheken) der Goldstandard. Es trennt Ihre Anliegen, hält Ihre Architektur sauber und stellt sicher, dass die Mehrsprachigkeitsfähigkeit Ihrer Anwendung nicht von einem „Black-Box“-Compiler abhängt, der Ihre Absichten errät.
220
+ Für professionelle Anwendungen bleibt **Deklaratives Content-Management** (wie Intlayer oder etablierte Bibliotheken) der Goldstandard. Es trennt Ihre Anliegen, hält Ihre Architektur sauber und stellt sicher, dass die Mehrsprachigkeitsfähigkeit Ihrer Anwendung nicht von einem „Black-Box“-Compiler abhängt, der Ihre Absichten errät.