@intlayer/docs 9.3.1 → 9.3.2

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.
Files changed (60) hide show
  1. package/dist/cjs/generated/docs.entry.cjs +20 -0
  2. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  3. package/dist/esm/generated/docs.entry.mjs +20 -0
  4. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  5. package/dist/types/generated/docs.entry.d.ts +1 -0
  6. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  7. package/docs/ar/eslint.md +336 -0
  8. package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +1 -1
  9. package/docs/bn/eslint.md +336 -0
  10. package/docs/cs/eslint.md +336 -0
  11. package/docs/de/eslint.md +336 -0
  12. package/docs/en/eslint.md +336 -0
  13. package/docs/en-GB/eslint.md +336 -0
  14. package/docs/en-GB/intlayer_with_create_react_app.md +32 -35
  15. package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +1 -1
  16. package/docs/es/eslint.md +336 -0
  17. package/docs/fr/eslint.md +336 -0
  18. package/docs/hi/eslint.md +336 -0
  19. package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +1 -1
  20. package/docs/hi/intlayer_with_vite+svelte.md +2 -2
  21. package/docs/id/eslint.md +336 -0
  22. package/docs/it/eslint.md +336 -0
  23. package/docs/ja/eslint.md +336 -0
  24. package/docs/ja/intlayer_with_react_router_v7.md +1 -146
  25. package/docs/ja/intlayer_with_vite+react.md +5 -1
  26. package/docs/ko/eslint.md +336 -0
  27. package/docs/ko/intlayer_with_lynx+react.md +4 -0
  28. package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +1 -1
  29. package/docs/ko/intlayer_with_storybook.md +5 -5
  30. package/docs/nl/eslint.md +336 -0
  31. package/docs/pl/eslint.md +336 -0
  32. package/docs/pl/intlayer_with_astro.md +1 -114
  33. package/docs/pl/migration_from_i18next_to_intlayer.md +4 -0
  34. package/docs/pl/migration_from_next-i18next_to_intlayer.md +8 -4
  35. package/docs/pl/migration_from_next-intl_to_intlayer.md +11 -5
  36. package/docs/pl/migration_from_nuxtjs_i18n_to_intlayer.md +8 -4
  37. package/docs/pl/migration_from_react-i18next_to_intlayer.md +8 -4
  38. package/docs/pl/migration_from_vue-i18n_to_intlayer.md +4 -0
  39. package/docs/pt/eslint.md +336 -0
  40. package/docs/pt/intlayer_with_astro.md +1 -114
  41. package/docs/ru/eslint.md +336 -0
  42. package/docs/tr/eslint.md +336 -0
  43. package/docs/uk/eslint.md +336 -0
  44. package/docs/uk/packages/angular-intlayer/exports.md +2 -2
  45. package/docs/ur/eslint.md +336 -0
  46. package/docs/vi/eslint.md +336 -0
  47. package/docs/zh/eslint.md +336 -0
  48. package/docs/zh/intlayer_with_create_react_app.md +4 -0
  49. package/docs/zh/intlayer_with_lynx+react.md +4 -0
  50. package/docs/zh/intlayer_with_nextjs_14.md +0 -2
  51. package/docs/zh/intlayer_with_nextjs_15.md +0 -2
  52. package/docs/zh/intlayer_with_nextjs_page_router.md +0 -2
  53. package/docs/zh/intlayer_with_nuxt.md +1 -1
  54. package/docs/zh/intlayer_with_react_router_v7.md +4 -0
  55. package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +4 -0
  56. package/docs/zh/intlayer_with_solid_start.md +1 -1
  57. package/docs/zh/intlayer_with_vite+vue.md +0 -2
  58. package/docs/zh-TW/eslint.md +336 -0
  59. package/package.json +6 -6
  60. package/src/generated/docs.entry.ts +20 -0
@@ -0,0 +1,336 @@
1
+ ---
2
+ createdAt: 2026-08-12
3
+ updatedAt: 2026-08-12
4
+ title: ESLint প্লাগইন | Intlayer এর জন্য লিন্ট নিয়ম
5
+ description: eslint-plugin-intlayer ব্যবহার করে হার্ডকোডেড স্ট্রিং, ডাইনামিক কল যা Intlayer কম্পাইলার অপ্টিমাইজ করতে পারে না এবং অব্যবহৃত ডিকশনারি সামগ্রী শনাক্ত করুন। React, Vue, Svelte, Angular এবং Astro জুড়ে ESLint এবং oxlint এর সাথে কাজ করে।
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - লিন্টিং
11
+ - i18n
12
+ - আন্তর্জাতিকীকরণ
13
+ - no-raw-text
14
+ - হার্ডকোডেড স্ট্রিং
15
+ - অব্যবহৃত অনুবাদ
16
+ - মৃত সামগ্রী
17
+ - React
18
+ - Vue
19
+ - Svelte
20
+ - Angular
21
+ slugs:
22
+ - doc
23
+ - eslint
24
+ history:
25
+ - version: 9.3.1
26
+ date: 2026-08-12
27
+ changes: "প্রাথমিক ইতিহাস"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # ESLint x OXLint প্লাগইন
32
+
33
+ `eslint-plugin-intlayer` এমন ধরনের i18n ভুলগুলো শনাক্ত করে যা TypeScript ধরতে পারে না:
34
+
35
+ 1. **হার্ডকোডেড টেক্সট** যা কখনই কোনো ডিকশনারিতে স্থান পায়নি।
36
+ 2. **ডাইনামিক কল** যা টাইপ-চেক পাস করে এবং রান হয়, কিন্তু Intlayer কম্পাইলার অপ্টিমাইজ করতে পারে না।
37
+ 3. **মৃত সামগ্রী (Dead content)** — ডিকশনারি এবং ফিল্ড যা প্রজেক্টের কোথাও রিড করা হয় না (ঐচ্ছিক/opt-in)।
38
+
39
+ অজানা ডিকশনারি কি, অজানা ফিল্ড পাথ এবং অনুপস্থিত লোকেলগুলো ইতিমধ্যেই কম্পাইল এরর, তাই প্লাগইন সেগুলো পুনরাবৃত্তি করে না।
40
+
41
+ ## ইনস্টলেশন
42
+
43
+ ```bash packageManager="npm"
44
+ npm install --save-dev eslint-plugin-intlayer
45
+ ```
46
+
47
+ ```bash packageManager="pnpm"
48
+ pnpm add --save-dev eslint-plugin-intlayer
49
+ ```
50
+
51
+ ```bash packageManager="yarn"
52
+ yarn add --dev eslint-plugin-intlayer
53
+ ```
54
+
55
+ ESLint 9 বা পরবর্তী সংস্করণ (flat config) প্রয়োজন।
56
+
57
+ ## ব্যবহার
58
+
59
+ প্লাগইনটি ESLint এবং [oxlint](https://oxc.rs) উভয় পরিবেশেই একই নিয়ম ও একই বিকল্প সহ কাজ করে।
60
+
61
+ <Tabs defaultTab="eslint">
62
+ <Tab label="ESLint" value="eslint">
63
+
64
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
65
+ import intlayer from "eslint-plugin-intlayer";
66
+
67
+ export default [...intlayer.configs.recommended];
68
+ ```
69
+
70
+ অথবা একে একে নিয়মগুলো সক্ষম করুন:
71
+
72
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
73
+ import intlayer from "eslint-plugin-intlayer";
74
+
75
+ export default [
76
+ {
77
+ plugins: { intlayer },
78
+ rules: {
79
+ "intlayer/no-raw-text": "warn",
80
+ "intlayer/static-dictionary-key": "error",
81
+ "intlayer/no-dynamic-field-access": "error",
82
+ "intlayer/enforce-adapter-import": "warn",
83
+ "intlayer/no-unused-content": "warn",
84
+ },
85
+ },
86
+ ];
87
+ ```
88
+
89
+ </Tab>
90
+ <Tab label="oxlint" value="oxlint">
91
+
92
+ ```json fileName=".oxlintrc.json"
93
+ {
94
+ "jsPlugins": ["eslint-plugin-intlayer"],
95
+ "rules": {
96
+ "intlayer/no-raw-text": "warn",
97
+ "intlayer/static-dictionary-key": "error",
98
+ "intlayer/no-dynamic-field-access": "error",
99
+ "intlayer/enforce-adapter-import": "warn"
100
+ }
101
+ }
102
+ ```
103
+
104
+ দুটি বিষয় মনে রাখবেন: oxlint এর JS প্লাগইন সমর্থন এখনও আলফা পর্যায়ে রয়েছে এবং oxlint কাস্টম পার্সার সমর্থন করে না — তাই `.vue`, `.svelte`, `.astro` এবং Angular টেমপ্লেট সেখানে লিন্ট করা হয় না। আপনার JS/TS/JSX ফাইলগুলোর জন্য oxlint চালান এবং বাকিগুলোর জন্য ESLint ব্যবহার করুন।
105
+
106
+ উপরে `no-unused-content` ইচ্ছাকৃতভাবে বাদ দেওয়া হয়েছে: এটির রুল কনটেক্সট থেকে ওয়ার্কিং ডিরেক্টরি এবং লিন্ট করা ফাইল পাথ প্রয়োজন, যা আলফা JS প্লাগইন ব্রিজ নিশ্চিত করে না। এটি ESLint এর অধীনে চালান।
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### কনফিগারেশনসমূহ (Configs)
112
+
113
+ | কনফিগারেশন | `no-raw-text` | `static-dictionary-key` | `no-dynamic-field-access` | `enforce-adapter-import` | `no-unused-content` |
114
+ | --------------- | ----------------------- | ----------------------- | ------------------------- | ------------------------ | ------------------- |
115
+ | `recommended` | warn | error | error | off | off |
116
+ | `strict` | error (+ অ-JSX লিটারেল) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ `recommended` ইচ্ছাকৃতভাবে `no-raw-text` কে `warn` হিসেবে রাখে: এটি বিদ্যমান কোনো কোডবেসে প্রয়োগ করলে সমস্ত অননূদিত স্ট্রিং একসাথে প্রকাশ পায়, যা প্রথম দিনেই আপনার বিল্ড ভেঙে ফেলা উচিত নয়।
120
+
121
+ `enforce-adapter-import` ডিফল্টভাবে বন্ধ থাকে — প্রয়োজন হলে স্পষ্টভাবে সক্ষম করুন।
122
+
123
+ `no-unused-content` প্রতিটি কনফিগারেশনেই বন্ধ থাকে, যার মধ্যে `strict` ও অন্তর্ভুক্ত। এটি একমাত্র নিয়ম যা আপনার Intlayer কনফিগারেশন পড়ে এবং ডিস্ক থেকে সোর্স ফাইলগুলো স্ক্যান করে, তাই এটি চালু করা একটি সুচিন্তিত সিদ্ধান্ত হওয়া উচিত।
124
+
125
+ ## নিয়মাবলী
126
+
127
+ ### `no-raw-text`
128
+
129
+ ডিকশনারিতে ঘোষিত নয় এমন ব্যবহারকারী-মুখী টেক্সট রিপোর্ট করে। এটি `intlayer extract` এর মতো একই সনাক্তকরণ ব্যবহার করে, তাই ব্র্যান্ডের নাম, CSS ক্লাস এবং প্রযুক্তিগত শনাক্তকারীগুলোকে উপেক্ষা করা হয়।
130
+
131
+ ```jsx
132
+ // ✗ রিপোর্ট করা হয়েছে
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ সঠিক
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ কন্টেন্ট ডিক্লারেশন ফাইলগুলো (`*.content.ts`, …) বাদ দেওয়া হয়।
142
+
143
+ একবারে পুরো ফাইল ঠিক করতে, `npx intlayer extract` চালান এবং কম্পাইলারকে স্ট্রিংগুলো ডিকশনারিতে সরিয়ে নিতে দিন।
144
+
145
+ **বিকল্পসমূহ**
146
+
147
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // যেসব বৈশিষ্ট্যের মান ব্যবহারকারী-মুখী টেক্সট।
153
+ // ডিফল্ট: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // যেসব উপাদানের সামগ্রী কখনই ব্যবহারকারী-মুখী টেক্সট নয়।
157
+ // ডিফল্ট: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // কখনই রিপোর্ট না করার টেক্সটের জন্য রেগুলার এক্সপ্রেশন।
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // মার্কআপের বাইরের স্ট্রিং লিটারেলগুলোও রিপোর্ট করবেন কিনা। ডিফল্ট: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ ডিকশনারি কি একটি স্ট্রিং লিটারেল হওয়া প্রয়োজন।
173
+
174
+ কম্পাইলার কেবল তখনই একটি ডিকশনারি প্রি-লোড করতে পারে যখন এটি কল সাইটে সরাসরি কি পড়তে পারে। একটি কম্পিউটেড কি-এর ক্ষেত্রে এটি নীরবে অপ্টিমাইজেশন এড়িয়ে যায় এবং পরিবর্তে প্রতিটি ডিকশনারি বান্ডেল করে।
175
+
176
+ ```typescript
177
+ // ✗ রিপোর্ট করা হয়েছে
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ ভেরিয়েবল এখনও লিটারেল নয়
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ সঠিক
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ এটি `useIntlayer`, `getIntlayer` এবং প্রতিটি সামঞ্জস্যপূর্ণ অ্যাডাপ্টারের (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …) ক্ষেত্রে প্রযোজ্য।
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ ডিকশনারি থেকে যে ফিল্ডটি আপনি পড়েন তা স্ট্যাটিকভাবে জানা থাকা প্রয়োজন।
196
+
197
+ কম্পাইলার সেই ফিল্ডগুলো সরিয়ে দেয় যেগুলোর ব্যবহার সে দেখতে পায় না। একটি কম্পিউটেড অ্যাক্সেস কম্পাইলারের কাছে অদৃশ্য থাকে, তাই রানটাইমে রিড `undefined` রিটার্ন করতে পারে।
198
+
199
+ ```typescript
200
+ // ✗ রিপোর্ট করা হয়েছে
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ সঠিক
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ মূল প্যাকেজের চেয়ে `@intlayer/*` কম্প্যাটিবিলিটি অ্যাডাপ্টারকে অগ্রাধিকার দেয়। মূল প্যাকেজ শুধুমাত্র তখনই Intlayer এ সমাধান হয় যখন বান্ডলার উপনাম কনফিগার করা থাকে; অ্যাডাপ্টার সর্বদা সমাধান করে। `--fix` এর মাধ্যমে স্বয়ংক্রিয়ভাবে সংশোধনযোগ্য।
217
+
218
+ ```typescript
219
+ // ✗ রিপোর্ট করা হয়েছে
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ সঠিক
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **ডিফল্টভাবে বন্ধ।** প্রজেক্টে কোনো অংশ যে সামগ্রী পড়ে না, এবং একাধিক স্থানে ঘোষিত ডিকশনারি কিগুলো রিপোর্ট করে।
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ প্রজেক্টে কোনো কলার "home" না চাইলে রিপোর্ট করা হয়
235
+ content: {
236
+ title: t({ bn: "শিরোনাম", en: "Title" }),
237
+
238
+ // ✗ যখন কিছুই `hero` পড়ে না তখন রিপোর্ট করা হয়
239
+ hero: {
240
+ subtitle: t({ bn: "উপশিরোনাম", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ অন্যান্য নিয়মের মতো এটি কেবল সামনে থাকা ফাইল থেকে সিদ্ধান্ত নিতে পারে না — একটি ফিল্ড শুধুমাত্র সম্পূর্ণ প্রজেক্টের সাপেক্ষেই অব্যবহৃত হিসেবে গণ্য হয়। লিন্ট রানের প্রথম কন্টেন্ট ডিক্লারেশনে এটি আপনার Intlayer কনফিগারেশন লোড করে, সেই কনফিগারেশনে ঘোষিত সোর্স ফাইলগুলো স্ক্যান করে (`build.traversePattern`, `compiler.transformPattern`) এবং একই ব্যবহার বিশ্লেষক চালায় যা `@intlayer/lsp` এবং VS Code এক্সটেনশনের "অব্যবহৃত" স্ট্রাইকথ্রু সমর্থন করে। ফলাফলটি `cacheTtl` মিলিসেকেন্ডের জন্য ক্যাশ থাকে, তাই প্রতিটি ফাইলের পরিবর্তে প্রতি রানে একবার স্ক্যান হয়।
247
+
248
+ **বিকল্পসমূহ**
249
+
250
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // যে ডিকশনারি কিগুলোতে কিছুই রেফারেন্স করে না তা রিপোর্ট করুন। ডিফল্ট: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // যে কন্টেন্ট ফিল্ডগুলো কিছুই পড়ে না তা রিপোর্ট করুন। ডিফল্ট: true
259
+ reportUnusedFields: true,
260
+
261
+ // একাধিক স্থানে ঘোষিত কিগুলো রিপোর্ট করুন। ডিফল্ট: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // কখনই রিপোর্ট না করার ফিল্ড পাথের রেগুলার এক্সপ্রেশন।
265
+ ignoreFields: ["^meta"],
266
+
267
+ // প্রজেক্ট রুট যেখান থেকে স্ক্যান শুরু হয়। ডিফল্ট: ESLint ওয়ার্কিং ডিরেক্টরি
268
+ baseDir: process.cwd(),
269
+
270
+ // প্রজেক্ট স্ক্যান কতক্ষণ পুনঃব্যবহার করা হবে (ms এ)। ডিফল্ট: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ যখন আপনি দীর্ঘমেয়াদী এডিটর সার্ভার থেকে লিন্ট করেন এবং চান পরিবর্তনগুলো দ্রুত প্রতিফলিত হোক, তখন `cacheTtl` হ্রাস করুন; একটি মনোরেপোতে একাধিক Intlayer প্রজেক্ট বিস্তৃত হলে `baseDir` সেট করুন।
278
+
279
+ > **ভুল রিপোর্টিং এড়াতে এটি নীরব থাকতে পছন্দ করে।** একটি মিথ্যা ইতিবাচক রিপোর্ট একটি অনুবাদ মুছে দিতে পারে, তাই যখন ডিকশনারি এমনভাবে ব্যবহার করা হয় যা বিশ্লেষণ ট্র্যাক করতে পারে না, তখন কিছুই রিপোর্ট করা হয় না: সামগ্রী অবজেক্টটি সম্পূর্ণরূপে পাস করা, এটি থেকে আবদ্ধ একটি অনুবাদক ফাংশন (`const t = useTranslations("home")`), সরাসরি ইম্পোর্টের মাধ্যমে পৌঁছানো একটি ঘোষণা (`useDictionary(myDictionary)`), অন্য ডিকশনারি থেকে একটি `nest()`, বা স্প্রেড অপারেটর দ্বারা অসম্পূর্ণ করা একটি ফিল্ড তালিকা। একক-ফাইল উপাদানগুলো (`.vue`, `.svelte`, `.astro`) তাদের উল্লিখিত ডিকশনারির প্রতিটি ফিল্ড ব্যবহার করছে বলে গণ্য হয়, কারণ তাদের স্ক্রিপ্ট ব্লকগুলো এখানে পার্স করা হয় না।
280
+
281
+ `reportDuplicateKeys` বিল্ডের মাধ্যমে `.intlayer/` এর অধীনে সংরক্ষিত অপরিশোধিত ডিকশনারি পড়ে, তাই প্রজেক্টটি কমপক্ষে একবার বিল্ড না হওয়া পর্যন্ত এটি নীরব থাকে। দুটি ঘোষণা একই কি শেয়ার করলে সেগুলো মার্জ হয়, যা একটি বৈধ প্যাটার্ন — রিপোর্টটি বিদ্যমান কারণ উভয় পাশে সংজ্ঞায়িত একটি ফিল্ড নীরবে দুটি মানের মধ্যে কেবল একটি ধরে রাখে।
282
+
283
+ বিশ্লেষকটি `@intlayer/lsp` থেকে লোড হয়, যা ESM হিসেবে সরবরাহ করা হয়। তাই নিয়মটির জন্য একটি Node সংস্করণ প্রয়োজন যা একটি ES মডিউলকে `require()` করতে সক্ষম — Node 20.19+ বা 22.12+। পুরনো সংস্করণে এটি লিন্ট রান ব্যর্থ না করে কিছুই রিপোর্ট করে না।
284
+
285
+ ## ফ্রেমওয়ার্কসমূহ
286
+
287
+ প্রতিটি নিয়ম Vue, Svelte এবং Angular টেমপ্লেট সহ সমস্ত Intlayer ইন্টিগ্রেশনে কাজ করে। আপনাকে শুধুমাত্র ESLint কে জানাতে হবে কোন পার্সার প্রতিটি ফাইলের ধরন পড়ে।
288
+
289
+ | ফ্রেমওয়ার্ক | ফাইলসমূহ | পার্সার |
290
+ | ------------------------- | ----------------- | --------------------------------- |
291
+ | React, Preact, Solid, Lit | `.jsx` `.tsx` | `typescript-eslint` |
292
+ | Next.js | `.jsx` `.tsx` | `typescript-eslint` |
293
+ | Vue, Nuxt | `.vue` | `vue-eslint-parser` |
294
+ | Svelte, SvelteKit | `.svelte` | `svelte-eslint-parser` |
295
+ | Angular | `.ts` | `typescript-eslint` |
296
+ | Angular টেমপ্লেট | `.component.html` | `@angular-eslint/template-parser` |
297
+ | Astro | `.astro` | `astro-eslint-parser` |
298
+
299
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
300
+ import intlayer from "eslint-plugin-intlayer";
301
+ import tseslint from "typescript-eslint";
302
+ import vueParser from "vue-eslint-parser";
303
+ import svelteParser from "svelte-eslint-parser";
304
+ import angularTemplateParser from "@angular-eslint/template-parser";
305
+
306
+ export default [
307
+ ...intlayer.configs.recommended,
308
+
309
+ {
310
+ files: ["**/*.{ts,tsx,jsx}"],
311
+ languageOptions: { parser: tseslint.parser },
312
+ },
313
+ {
314
+ files: ["**/*.vue"],
315
+ languageOptions: {
316
+ parser: vueParser,
317
+ parserOptions: { parser: tseslint.parser },
318
+ },
319
+ },
320
+ {
321
+ files: ["**/*.svelte"],
322
+ languageOptions: {
323
+ parser: svelteParser,
324
+ parserOptions: { parser: tseslint.parser },
325
+ },
326
+ },
327
+ {
328
+ files: ["**/*.component.html"],
329
+ languageOptions: { parser: angularTemplateParser },
330
+ },
331
+ ];
332
+ ```
333
+
334
+ আপনার প্রজেক্টের জন্য প্রয়োজনীয় পার্সারগুলো কেবল ইনস্টল করুন।
335
+
336
+ > **পরিচিত সীমাবদ্ধতা।** Vue এবং Angular টেমপ্লেটে `{{ content[key] }}` এর মতো এক্সপ্রেশন `no-dynamic-field-access` দ্বারা পরীক্ষা করা হয় না। স্ক্রিপ্ট ব্লকে লেখা ডাইনামিক রিডগুলো স্বাভাবিকভাবেই ধরা পড়ে।
@@ -0,0 +1,336 @@
1
+ ---
2
+ createdAt: 2026-08-12
3
+ updatedAt: 2026-08-12
4
+ title: Plugin ESLint | Pravidla lintování pro Intlayer
5
+ description: Odhalujte natvrdo zapsané řetězce, dynamická volání, která kompilátor Intlayer nedokáže optimalizovat, a nepoužitý obsah slovníků pomocí eslint-plugin-intlayer. Funguje s ESLint a oxlint v Reactu, Vue, Svelte, Angularu a Astru.
6
+ keywords:
7
+ - Intlayer
8
+ - ESLint
9
+ - oxlint
10
+ - Linting
11
+ - i18n
12
+ - Internacionalizace
13
+ - no-raw-text
14
+ - Hardcoded řetězce
15
+ - Nepoužité překlady
16
+ - Mrtvý obsah
17
+ - React
18
+ - Vue
19
+ - Svelte
20
+ - Angular
21
+ slugs:
22
+ - doc
23
+ - eslint
24
+ history:
25
+ - version: 9.3.1
26
+ date: 2026-08-12
27
+ changes: "Počáteční historie"
28
+ author: aymericzip
29
+ ---
30
+
31
+ # Plugin ESLint x OXLint
32
+
33
+ `eslint-plugin-intlayer` zachycuje typy chyb i18n, které TypeScript nedokáže odhalit:
34
+
35
+ 1. **Natvrdo zapsaný text (hardcoded text)**, který nebyl vložen do slovníku.
36
+ 2. **Dynamická volání**, která projdou typovou kontrolou a fungují, ale kompilátor Intlayer je nedokáže optimalizovat.
37
+ 3. **Mrtvý obsah (Dead content)** — slovníky a pole, které v projektu nic nečte (volitelné / opt-in).
38
+
39
+ Neznámé klíče slovníků, neznámé cesty polí a chybějící lokality jsou již chybami kompilace, takže je plugin neopakuje.
40
+
41
+ ## Instalace
42
+
43
+ ```bash packageManager="npm"
44
+ npm install --save-dev eslint-plugin-intlayer
45
+ ```
46
+
47
+ ```bash packageManager="pnpm"
48
+ pnpm add --save-dev eslint-plugin-intlayer
49
+ ```
50
+
51
+ ```bash packageManager="yarn"
52
+ yarn add --dev eslint-plugin-intlayer
53
+ ```
54
+
55
+ Vyžaduje ESLint 9 nebo novější (flat config).
56
+
57
+ ## Použití
58
+
59
+ Plugin funguje jak v ESLint, tak v [oxlint](https://oxc.rs) — se stejnými pravidly a možnostmi.
60
+
61
+ <Tabs defaultTab="eslint">
62
+ <Tab label="ESLint" value="eslint">
63
+
64
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
65
+ import intlayer from "eslint-plugin-intlayer";
66
+
67
+ export default [...intlayer.configs.recommended];
68
+ ```
69
+
70
+ Nebo aktivujte pravidla jednotlivě:
71
+
72
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
73
+ import intlayer from "eslint-plugin-intlayer";
74
+
75
+ export default [
76
+ {
77
+ plugins: { intlayer },
78
+ rules: {
79
+ "intlayer/no-raw-text": "warn",
80
+ "intlayer/static-dictionary-key": "error",
81
+ "intlayer/no-dynamic-field-access": "error",
82
+ "intlayer/enforce-adapter-import": "warn",
83
+ "intlayer/no-unused-content": "warn",
84
+ },
85
+ },
86
+ ];
87
+ ```
88
+
89
+ </Tab>
90
+ <Tab label="oxlint" value="oxlint">
91
+
92
+ ```json fileName=".oxlintrc.json"
93
+ {
94
+ "jsPlugins": ["eslint-plugin-intlayer"],
95
+ "rules": {
96
+ "intlayer/no-raw-text": "warn",
97
+ "intlayer/static-dictionary-key": "error",
98
+ "intlayer/no-dynamic-field-access": "error",
99
+ "intlayer/enforce-adapter-import": "warn"
100
+ }
101
+ }
102
+ ```
103
+
104
+ Dvě upozornění: podpora JS pluginů v oxlint je stále ve fázi alfa a oxlint nepodporuje vlastní parsery — proto zde soubory `.vue`, `.svelte`, `.astro` a šablony Angularu nejsou kontrolovány. Spusťte oxlint na souborech JS/TS/JSX a pro zbytek použijte ESLint.
105
+
106
+ Pravidlo `no-unused-content` je výše záměrně vynecháno: vyžaduje pracovní adresář a cestu ke kontrolovanému souboru z kontextu pravidla, což alfa můstek JS pluginů nezaručuje. Spusťte jej pod ESLintem.
107
+
108
+ </Tab>
109
+ </Tabs>
110
+
111
+ ### Konfigurace (Configs)
112
+
113
+ | Konfigurace | `no-raw-text` | `static-dictionary-key` | `no-dynamic-field-access` | `enforce-adapter-import` | `no-unused-content` |
114
+ | --------------- | --------------------------- | ----------------------- | ------------------------- | ------------------------ | ------------------- |
115
+ | `recommended` | warn | error | error | off | off |
116
+ | `strict` | error (+ literály mimo JSX) | error | error | error | off |
117
+ | `contract-only` | off | error | error | off | off |
118
+
119
+ Předvolba `recommended` záměrně ponechává `no-raw-text` na úrovni `warn`: její spuštění nad existující kódovou bází zobrazí všechny nepřeložené řetězce najednou, což by nemělo rozbít váš build hned první den.
120
+
121
+ `enforce-adapter-import` je ve výchozím nastavení vypnuto — pokud jej chcete, explicitně jej zapněte.
122
+
123
+ `no-unused-content` je vypnuto ve všech konfiguracích včetně `strict`. Je to jediné pravidlo, které čte vaši konfiguraci Intlayer a prochází zdrojové soubory z disku, takže jeho zapnutí by mělo být záměrnou volbou, nikoli automatickou předvolbou.
124
+
125
+ ## Pravidla
126
+
127
+ ### `no-raw-text`
128
+
129
+ Hlásí text určený pro uživatele, který není deklarován ve slovníku. Používá stejnou detekci jako `intlayer extract`, takže názvy značek, třídy CSS a technické identifikátory jsou ignorovány.
130
+
131
+ ```jsx
132
+ // ✗ Nahlášeno
133
+ <h1>Welcome to our documentation</h1>
134
+ <input placeholder="Enter your email address" />
135
+
136
+ // ✓ V pořádku
137
+ const { title } = useIntlayer("home");
138
+ <h1>{title}</h1>
139
+ ```
140
+
141
+ Soubory deklarace obsahu (`*.content.ts`, …) jsou přeskočeny.
142
+
143
+ Chcete-li opravit celý soubor najednou, spusťte `npx intlayer extract` a nechte kompilátor přesunout řetězce do slovníku za vás.
144
+
145
+ **Možnosti**
146
+
147
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
148
+ {
149
+ "intlayer/no-raw-text": [
150
+ "warn",
151
+ {
152
+ // Atributy, jejichž hodnotou je text pro uživatele.
153
+ // Výchozí: title, placeholder, alt, aria-label, label
154
+ attributes: ["title", "placeholder", "alt", "aria-label", "label"],
155
+
156
+ // Elementy, jejichž obsah nikdy není textem pro uživatele.
157
+ // Výchozí: code, pre, script, style
158
+ ignoreElements: ["code", "pre", "script", "style"],
159
+
160
+ // Regulární výrazy pro text, který se nemá nikdy hlásit.
161
+ ignorePatterns: ["^Powered by"],
162
+
163
+ // Hlásit také řetězcové literály mimo značky. Výchozí: false
164
+ includeStringLiterals: false,
165
+ },
166
+ ],
167
+ }
168
+ ```
169
+
170
+ ### `static-dictionary-key`
171
+
172
+ Vyžaduje, aby klíč slovníku byl řetězcový literál.
173
+
174
+ Kompilátor může přednačíst slovník pouze tehdy, když dokáže přečíst klíč přímo v místě volání. Při použití vypočteného klíče optimalizaci tiše přeskočí a místo toho přibalí každý slovník.
175
+
176
+ ```typescript
177
+ // ✗ Nahlášeno
178
+ useIntlayer(dictionaryKey);
179
+ useIntlayer(`home-${suffix}`);
180
+ getTranslations({ namespace: page });
181
+
182
+ // ✗ Proměnná stále není literál
183
+ const key = "home";
184
+ useIntlayer(key);
185
+
186
+ // ✓ V pořádku
187
+ useIntlayer("home");
188
+ getTranslations({ namespace: "home" });
189
+ ```
190
+
191
+ To platí pro `useIntlayer`, `getIntlayer` a všechny kompatibilní adaptéry (`useTranslation`, `useTranslations`, `formatMessage`, `<FormattedMessage id>`, `<Trans i18nKey>`, …).
192
+
193
+ ### `no-dynamic-field-access`
194
+
195
+ Vyžaduje, aby pole, které čtete ze slovníku, bylo staticky známé.
196
+
197
+ Kompilátor odstraňuje pole, u kterých nevidí využití. Dynamický přístup je pro něj neviditelný, takže čtení může za běhu vrátit `undefined`.
198
+
199
+ ```typescript
200
+ // ✗ Nahlášeno
201
+ const content = useIntlayer("home");
202
+ content[fieldName];
203
+
204
+ const t = useTranslations("home");
205
+ t(messageKey);
206
+
207
+ // ✓ V pořádku
208
+ content.title;
209
+ content["title"];
210
+ content.items[0];
211
+ t("hero.title");
212
+ ```
213
+
214
+ ### `enforce-adapter-import`
215
+
216
+ Dává přednost kompatibilnímu adaptéru `@intlayer/*` před původním balíčkem. Původní balíček se na Intlayer překládá pouze při nakonfigurovaném aliasu bundleru; adaptér funguje vždy. Automaticky opravitelné pomocí `--fix`.
217
+
218
+ ```typescript
219
+ // ✗ Nahlášeno
220
+ import { useTranslation } from "react-i18next";
221
+ import { getTranslations } from "next-intl/server";
222
+
223
+ // ✓ V pořádku
224
+ import { useTranslation } from "@intlayer/react-i18next";
225
+ import { getTranslations } from "@intlayer/next-intl/server";
226
+ ```
227
+
228
+ ### `no-unused-content`
229
+
230
+ **Ve výchozím nastavení vypnuto.** Hlásí obsah, který v projektu nic nečte, a navíc klíče slovníků deklarované na více než jednom místě.
231
+
232
+ ```typescript fileName="src/home.content.ts"
233
+ export default {
234
+ key: "home", // ✗ Nahlášeno, pokud žádný volající v projektu nežádá "home"
235
+ content: {
236
+ title: t({ cs: "Název", en: "Title" }),
237
+
238
+ // ✗ Nahlášeno, pokud nic nečte `hero`
239
+ hero: {
240
+ subtitle: t({ cs: "Podnázev", en: "Subtitle" }),
241
+ },
242
+ },
243
+ };
244
+ ```
245
+
246
+ Na rozdíl od jiných pravidel toto pravidlo nemůže rozhodnout pouze na základě otevřeného souboru — pole je nepoužité pouze ve vztahu k celému projektu. Při první deklaraci obsahu v běhu lintu načte vaši konfiguraci Intlayer, prohledá zdrojové soubory podle konfigurace (`build.traversePattern`, `compiler.transformPattern`) a spustí stejný analyzátor využití, který pohání `@intlayer/lsp` a přeškrtnutí „nepoužitého“ v rozšíření VS Code. Výsledek se ukládá do mezipaměti na `cacheTtl` milisekund, takže skenování proběhne jednou za běh a nikoli pro každý soubor.
247
+
248
+ **Možnosti**
249
+
250
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
251
+ {
252
+ "intlayer/no-unused-content": [
253
+ "warn",
254
+ {
255
+ // Hlásit klíče slovníků, na které nic neodkazuje. Výchozí: true
256
+ reportUnusedDictionaries: true,
257
+
258
+ // Hlásit pole obsahu, která nic nečte. Výchozí: true
259
+ reportUnusedFields: true,
260
+
261
+ // Hlásit duplicitní klíče deklarované na více místech. Výchozí: true
262
+ reportDuplicateKeys: true,
263
+
264
+ // Regulární výrazy pro cesty polí, které se nemají nikdy hlásit.
265
+ ignoreFields: ["^meta"],
266
+
267
+ // Kořen projektu, od kterého skenování začíná. Výchozí: pracovní adresář ESLint
268
+ baseDir: process.cwd(),
269
+
270
+ // Doba opětovného použití skenu projektu (v ms). Výchozí: 30000
271
+ cacheTtl: 30000,
272
+ },
273
+ ],
274
+ }
275
+ ```
276
+
277
+ Snižte `cacheTtl`, pokud lintujete z dlouhotrvajícího serveru editoru a chcete, aby se úpravy projevily dříve; nastavte `baseDir`, když jeden běh lintu zahrnuje několik projektů Intlayer v monorepu.
278
+
279
+ > **Přiklání se k tichu.** Falešně pozitivní výsledek by zde smazal překlad, proto se nic nehlásí, pokud je slovník konzumován způsobem, který analýza nedokáže sledovat: objekt obsahu předaný jako celek, překladatelská funkce vázaná z něj (`const t = useTranslations("home")`), deklarace dosažená přímým importem (`useDictionary(myDictionary)`), volání `nest()` z jiného slovníku nebo seznam polí neúplný kvůli operátoru spread. Jednosouborové komponenty (`.vue`, `.svelte`, `.astro`) se počítají jako využívající každé pole zmíněných slovníků, protože jejich bloky skriptů se zde neparsují.
280
+
281
+ `reportDuplicateKeys` čte nesloučené slovníky, které build zapisuje do `.intlayer/`, takže zůstává neaktivní, dokud projekt nebyl alespoň jednou sestaven. Dvě deklarace sdílející klíč se sloučí, což je legitimní vzor — hlášení existuje proto, že pole definované na obou stranách tiše zachová pouze jednu ze dvou hodnot.
282
+
283
+ Analyzátor se načítá z `@intlayer/lsp`, který je distribuován jako ESM. Pravidlo proto vyžaduje verzi Node schopnou provést `require()` modulu ES — Node 20.19+ nebo 22.12+. Na starších verzích raději nehlásí nic, než aby způsobilo selhání lintu.
284
+
285
+ ## Frameworky
286
+
287
+ Každé pravidlo funguje ve všech integracích Intlayer, včetně šablon Vue, Svelte a Angularu. Stačí pouze určit ESLintu, který parser má číst daný typ souboru.
288
+
289
+ | Framework | Soubory | Parser |
290
+ | ------------------------- | ----------------- | --------------------------------- |
291
+ | React, Preact, Solid, Lit | `.jsx` `.tsx` | `typescript-eslint` |
292
+ | Next.js | `.jsx` `.tsx` | `typescript-eslint` |
293
+ | Vue, Nuxt | `.vue` | `vue-eslint-parser` |
294
+ | Svelte, SvelteKit | `.svelte` | `svelte-eslint-parser` |
295
+ | Angular | `.ts` | `typescript-eslint` |
296
+ | Šablony Angularu | `.component.html` | `@angular-eslint/template-parser` |
297
+ | Astro | `.astro` | `astro-eslint-parser` |
298
+
299
+ ```javascript fileName="eslint.config.mjs" codeFormat="esm"
300
+ import intlayer from "eslint-plugin-intlayer";
301
+ import tseslint from "typescript-eslint";
302
+ import vueParser from "vue-eslint-parser";
303
+ import svelteParser from "svelte-eslint-parser";
304
+ import angularTemplateParser from "@angular-eslint/template-parser";
305
+
306
+ export default [
307
+ ...intlayer.configs.recommended,
308
+
309
+ {
310
+ files: ["**/*.{ts,tsx,jsx}"],
311
+ languageOptions: { parser: tseslint.parser },
312
+ },
313
+ {
314
+ files: ["**/*.vue"],
315
+ languageOptions: {
316
+ parser: vueParser,
317
+ parserOptions: { parser: tseslint.parser },
318
+ },
319
+ },
320
+ {
321
+ files: ["**/*.svelte"],
322
+ languageOptions: {
323
+ parser: svelteParser,
324
+ parserOptions: { parser: tseslint.parser },
325
+ },
326
+ },
327
+ {
328
+ files: ["**/*.component.html"],
329
+ languageOptions: { parser: angularTemplateParser },
330
+ },
331
+ ];
332
+ ```
333
+
334
+ Nainstalujte pouze ty parsery, které váš projekt vyžaduje.
335
+
336
+ > **Známé omezení.** V šablonách Vue a Angularu výraz jako `{{ content[key] }}` není kontrolován pravidlem `no-dynamic-field-access`. Dynamická čtení zapsaná ve skriptovém bloku jsou zachycena normálně.