@hua-labs/i18n-beginner 2.0.0

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.
package/README_EN.md ADDED
@@ -0,0 +1,506 @@
1
+ # @hua-labs/i18n-beginner
2
+
3
+ [한국어](./README.md) | [English](#english)
4
+
5
+ ## This SDK is for Beginners!
6
+
7
+ > [View Demo](https://i18n-demo.hua-labs.com) | Contributing: [SDK Repo](https://github.com/HUA-Labs/HUA-Labs-public)
8
+
9
+ > Need advanced features?
10
+ > - **Beginner**: `@hua-labs/i18n-beginner` (current package) - Simple and intuitive
11
+ > - **Advanced**: `@hua-labs/i18n-sdk` - Full features, plugins, advanced settings
12
+ > - **Enterprise**: `@hua-labs/i18n-advanced` - Custom loaders, performance optimization, enterprise features
13
+
14
+ **This SDK is designed to get you started in 30 seconds!**
15
+
16
+ ---
17
+
18
+ ## English
19
+
20
+ **The simplest internationalization SDK for React beginners!**
21
+
22
+ A beginner-friendly i18n SDK that supports Korean and English out of the box, with easy support for additional languages.
23
+
24
+ ### Features
25
+ - **Zero Configuration**: Works out of the box with Korean and English
26
+ - **Easy Language Addition**: Add any language with simple functions
27
+ - **TypeScript Support**: Full type safety and IntelliSense
28
+ - **Next.js Compatible**: Works perfectly with App Router and Pages Router
29
+ - **No External Dependencies**: Lightweight and fast
30
+ - **80+ Built-in Translations**: Common UI elements pre-translated
31
+
32
+ ### Quick Start (30 seconds)
33
+ ```bash
34
+ npm install @hua-labs/i18n-beginner
35
+ ```
36
+
37
+ ```tsx
38
+ // app/layout.tsx
39
+ import { SimpleI18n } from '@hua-labs/i18n-beginner';
40
+
41
+ export default function RootLayout({ children }) {
42
+ return (
43
+ <html>
44
+ <body>
45
+ <SimpleI18n>
46
+ {children}
47
+ </SimpleI18n>
48
+ </body>
49
+ </html>
50
+ );
51
+ }
52
+ ```
53
+
54
+ ```tsx
55
+ // app/page.tsx
56
+ 'use client';
57
+ import { useSimpleI18n } from '@hua-labs/i18n-beginner';
58
+
59
+ export default function Home() {
60
+ const { t, toggleLanguage, languageButtonText } = useSimpleI18n();
61
+
62
+ return (
63
+ <div>
64
+ <h1>{t('welcome')}</h1>
65
+ <p>{t('hello')}</p>
66
+ <button onClick={toggleLanguage}>{languageButtonText}</button>
67
+ </div>
68
+ );
69
+ }
70
+ ```
71
+
72
+ ### Adding Other Languages
73
+ ```tsx
74
+ // Add Japanese
75
+ useEffect(() => {
76
+ addTranslation('ja', 'welcome', 'ようこそ');
77
+ addTranslation('ja', 'hello', 'こんにちは');
78
+ }, []);
79
+
80
+ // Or use TypeScript files
81
+ const japaneseTranslations = {
82
+ ja: {
83
+ welcome: "ようこそ",
84
+ hello: "こんにちは"
85
+ }
86
+ } as const;
87
+
88
+ useTranslationsFromFile(japaneseTranslations);
89
+ ```
90
+
91
+ ### Complete Beginner Checklist
92
+
93
+ #### Step 1: Installation Check
94
+ ```bash
95
+ # Did you run this command in terminal?
96
+ npm install @hua-labs/i18n-beginner
97
+ ```
98
+ > Check: Verify that `"@hua-labs/i18n-beginner"` exists in your `package.json`.
99
+
100
+ #### Step 2: Provider Setup Check
101
+ ```tsx
102
+ // Is this code in your layout.tsx?
103
+ import { SimpleI18n } from '@hua-labs/i18n-beginner';
104
+
105
+ <SimpleI18n>
106
+ {children}
107
+ </SimpleI18n>
108
+ ```
109
+ > Check: If the page loads without errors, you're successful!
110
+
111
+ #### Step 3: Component Usage Check
112
+ ```tsx
113
+ // Is this code in your component?
114
+ import { useSimpleI18n } from '@hua-labs/i18n-beginner';
115
+
116
+ const { t, toggleLanguage, languageButtonText } = useSimpleI18n();
117
+ ```
118
+ > Check: Does the language change when you click the button?
119
+
120
+ ### Built-in Translation Keys
121
+
122
+ #### Basic Greetings
123
+ ```tsx
124
+ t('welcome') // "Welcome"
125
+ t('hello') // "Hello"
126
+ t('click_me') // "Click me"
127
+ ```
128
+
129
+ #### Status Messages
130
+ ```tsx
131
+ t('loading') // "Loading..."
132
+ t('error') // "An error occurred"
133
+ t('success') // "Success"
134
+ ```
135
+
136
+ #### Button Text
137
+ ```tsx
138
+ t('cancel') // "Cancel"
139
+ t('confirm') // "Confirm"
140
+ t('save') // "Save"
141
+ t('delete') // "Delete"
142
+ t('edit') // "Edit"
143
+ t('add') // "Add"
144
+ ```
145
+
146
+ #### Search & Navigation
147
+ ```tsx
148
+ t('search') // "Search"
149
+ t('back') // "Back"
150
+ t('next') // "Next"
151
+ t('home') // "Home"
152
+ t('about') // "About"
153
+ t('contact') // "Contact"
154
+ ```
155
+
156
+ #### Settings & User
157
+ ```tsx
158
+ t('settings') // "Settings"
159
+ t('profile') // "Profile"
160
+ t('logout') // "Logout"
161
+ t('login') // "Login"
162
+ t('register') // "Register"
163
+ ```
164
+
165
+ #### Form Fields
166
+ ```tsx
167
+ t('email') // "Email"
168
+ t('password') // "Password"
169
+ t('name') // "Name"
170
+ t('phone') // "Phone"
171
+ t('address') // "Address"
172
+ ```
173
+
174
+ #### Action Buttons
175
+ ```tsx
176
+ t('submit') // "Submit"
177
+ t('reset') // "Reset"
178
+ t('close') // "Close"
179
+ t('open') // "Open"
180
+ t('yes') // "Yes"
181
+ t('no') // "No"
182
+ t('ok') // "OK"
183
+ ```
184
+
185
+ #### Long Messages
186
+ ```tsx
187
+ t('loading_text') // "Please wait..."
188
+ t('error_message') // "An error occurred. Please try again."
189
+ t('success_message') // "Successfully completed!"
190
+ t('not_found') // "Not found"
191
+ t('unauthorized') // "Unauthorized"
192
+ t('forbidden') // "Forbidden"
193
+ t('server_error') // "Server error occurred"
194
+ ```
195
+
196
+ ### Custom Translation Methods
197
+
198
+ #### Method 1: Dynamic Translation Addition
199
+ ```tsx
200
+ import { useSimpleI18n } from '@hua-labs/i18n-beginner';
201
+
202
+ function MyComponent() {
203
+ const { t, toggleLanguage, languageButtonText, addTranslation } = useSimpleI18n();
204
+
205
+ // Add translations
206
+ const addCustomTranslations = () => {
207
+ addTranslation('ko', 'custom_message', '커스텀 메시지');
208
+ addTranslation('en', 'custom_message', 'Custom message');
209
+ };
210
+
211
+ return (
212
+ <div>
213
+ <h1>{t('welcome')}</h1>
214
+ <p>{t('hello')}</p>
215
+ <p>{t('custom_message')}</p> {/* Use custom translation */}
216
+ <button onClick={addCustomTranslations}>Add Translation</button>
217
+ <button onClick={toggleLanguage}>{languageButtonText}</button>
218
+ </div>
219
+ );
220
+ }
221
+ ```
222
+
223
+ #### Method 2: TypeScript File Translation Separation (Recommended!)
224
+
225
+ **Step 1: Create translation file**
226
+ ```tsx
227
+ // translations/myTranslations.ts
228
+ export const myTranslations = {
229
+ ko: {
230
+ welcome_message: "환영합니다",
231
+ goodbye_message: "안녕히 가세요",
232
+ custom_button: "커스텀 버튼",
233
+ about_us: "우리에 대해",
234
+ contact_info: "연락처 정보"
235
+ },
236
+ en: {
237
+ welcome_message: "Welcome",
238
+ goodbye_message: "Goodbye",
239
+ custom_button: "Custom Button",
240
+ about_us: "About Us",
241
+ contact_info: "Contact Information"
242
+ }
243
+ } as const;
244
+ ```
245
+
246
+ **Step 2: Use in component**
247
+ ```tsx
248
+ import { useSimpleI18n, loadTranslationsFromFile } from '@hua-labs/i18n-beginner';
249
+ import { myTranslations } from './translations/myTranslations';
250
+
251
+ function MyComponent() {
252
+ const { t, addTranslation } = useSimpleI18n();
253
+
254
+ // Load translation file on component mount
255
+ useEffect(() => {
256
+ loadTranslationsFromFile(myTranslations, addTranslation);
257
+ }, []);
258
+
259
+ return (
260
+ <div>
261
+ <h1>{t('welcome_message')}</h1>
262
+ <p>{t('about_us')}</p>
263
+ <button>{t('custom_button')}</button>
264
+ </div>
265
+ );
266
+ }
267
+ ```
268
+
269
+ #### Method 3: Simpler Hook Usage
270
+ ```tsx
271
+ import { useSimpleI18n, useTranslationsFromFile } from '@hua-labs/i18n-beginner';
272
+ import { myTranslations } from './translations/myTranslations';
273
+
274
+ function MyComponent() {
275
+ const { t } = useSimpleI18n();
276
+
277
+ // Automatically load translation file
278
+ useTranslationsFromFile(myTranslations);
279
+
280
+ return (
281
+ <div>
282
+ <h1>{t('welcome_message')}</h1>
283
+ <p>{t('contact_info')}</p>
284
+ </div>
285
+ );
286
+ }
287
+ ```
288
+
289
+ ### Advanced Usage
290
+
291
+ #### Various Hooks
292
+
293
+ ##### 1. `useSimpleI18n` (Recommended!)
294
+ ```tsx
295
+ const { t, toggleLanguage, languageButtonText, isClient, addTranslation } = useSimpleI18n();
296
+ ```
297
+ > When to use: Use in most cases. It's the simplest!
298
+
299
+ ##### 2. `useTranslate` (When you only need translation)
300
+ ```tsx
301
+ const t = useTranslate();
302
+ ```
303
+ > When to use: Use when you only need the translation function.
304
+
305
+ ##### 3. `useLanguage` (When you only need language features)
306
+ ```tsx
307
+ const { language, setLanguage, toggleLanguage, addTranslation } = useLanguage();
308
+ ```
309
+ > When to use: Use when you only need language switching features.
310
+
311
+ ##### 4. `useI18n` (When you need all features)
312
+ ```tsx
313
+ const { t, language, setLanguage, toggleLanguage, addTranslation, isClient } = useI18n();
314
+ ```
315
+ > When to use: Use when you need all features.
316
+
317
+ #### Direct Language Setting
318
+
319
+ ```tsx
320
+ import { useLanguage } from '@hua-labs/i18n-beginner';
321
+
322
+ function LanguageSelector() {
323
+ const { setLanguage } = useLanguage();
324
+
325
+ return (
326
+ <div>
327
+ <button onClick={() => setLanguage('ko')}>한국어</button>
328
+ <button onClick={() => setLanguage('en')}>English</button>
329
+ </div>
330
+ );
331
+ }
332
+ ```
333
+
334
+ ### Important Notes
335
+
336
+ #### Hydration Problem Solution
337
+
338
+ You might encounter "hydration mismatch" errors in Next.js. Solve them like this:
339
+
340
+ ```tsx
341
+ import { useSimpleI18n } from '@hua-labs/i18n-beginner';
342
+
343
+ function MyComponent() {
344
+ const { t, toggleLanguage, languageButtonText, isClient } = useSimpleI18n();
345
+
346
+ // Prevent hydration
347
+ if (!isClient) {
348
+ return (
349
+ <div>
350
+ <h1>Welcome</h1>
351
+ <p>Hello</p>
352
+ <button>한국어</button>
353
+ </div>
354
+ );
355
+ }
356
+
357
+ return (
358
+ <div>
359
+ <h1>{t('welcome')}</h1>
360
+ <p>{t('hello')}</p>
361
+ <button onClick={toggleLanguage}>{languageButtonText}</button>
362
+ </div>
363
+ );
364
+ }
365
+ ```
366
+
367
+ #### Infinite Loop Prevention
368
+
369
+ When using `addTranslation` in `useEffect`, keep the dependency array empty:
370
+
371
+ ```tsx
372
+ // Correct method
373
+ useEffect(() => {
374
+ addTranslation('ko', 'my_text', '내 텍스트');
375
+ addTranslation('en', 'my_text', 'My text');
376
+ }, []); // Empty array
377
+
378
+ // Wrong method (causes infinite loop!)
379
+ useEffect(() => {
380
+ addTranslation('ko', 'my_text', '내 텍스트');
381
+ addTranslation('en', 'my_text', 'My text');
382
+ }, [addTranslation]); // Including addTranslation in dependencies
383
+ ```
384
+
385
+ ### Performance Optimization
386
+
387
+ #### Remove unnecessary translation keys
388
+ ```tsx
389
+ // Bad example: Adding unused translations
390
+ addTranslation('ko', 'unused_text', '사용하지 않는 텍스트');
391
+
392
+ // Good example: Only add necessary translations
393
+ addTranslation('ko', 'important_text', '중요한 텍스트');
394
+ ```
395
+
396
+ #### Prevent unnecessary re-renders
397
+ ```tsx
398
+ import { useMemo } from 'react';
399
+
400
+ function MyComponent() {
401
+ const { t } = useSimpleI18n();
402
+
403
+ // Memoize translated text (function itself doesn't need memoization)
404
+ const welcomeText = useMemo(() => t('welcome'), [t]);
405
+ const helloText = useMemo(() => t('hello'), [t]);
406
+
407
+ return (
408
+ <div>
409
+ <h1>{welcomeText}</h1>
410
+ <p>{helloText}</p>
411
+ </div>
412
+ );
413
+ }
414
+ ```
415
+
416
+ #### Add dynamic translations only when needed
417
+ ```tsx
418
+ // Bad example: Adding every render
419
+ function MyComponent() {
420
+ const { addTranslation } = useSimpleI18n();
421
+
422
+ addTranslation('ko', 'text', '텍스트'); // Runs every time!
423
+
424
+ return <div>...</div>;
425
+ }
426
+
427
+ // Good example: Add only once
428
+ function MyComponent() {
429
+ const { addTranslation } = useSimpleI18n();
430
+
431
+ useEffect(() => {
432
+ addTranslation('ko', 'text', '텍스트'); // Runs only once!
433
+ }, []);
434
+
435
+ return <div>...</div>;
436
+ }
437
+ ```
438
+
439
+ ### Security
440
+
441
+ #### Only get translation keys from trusted sources
442
+ ```tsx
443
+ // Bad example: Using user input directly
444
+ const userKey = userInput; // Dangerous!
445
+ t(userKey);
446
+
447
+ // Good example: Only use allowed keys
448
+ const allowedKeys = ['welcome', 'hello', 'goodbye'];
449
+ if (allowedKeys.includes(userKey)) {
450
+ t(userKey);
451
+ }
452
+ ```
453
+
454
+ ### FAQ
455
+
456
+ #### Q: How to support more languages?
457
+ A: Use the `addTranslation()` function to add them dynamically.
458
+
459
+ ```tsx
460
+ addTranslation('ja', 'welcome', 'ようこそ'); // Japanese
461
+ addTranslation('fr', 'welcome', 'Bienvenue'); // French
462
+ addTranslation('es', 'welcome', 'Bienvenido'); // Spanish
463
+ ```
464
+
465
+ #### Q: Translation not showing?
466
+ A: Check if the translation key is correct. Refer to the "Built-in Translation Keys" section.
467
+
468
+ #### Q: Can I add translations dynamically?
469
+ A: Yes! Use the `addTranslation()` function to add translations at runtime.
470
+
471
+ #### Q: Language not changing
472
+ A: Check if the `SimpleI18n` Provider is set up correctly.
473
+
474
+ #### Q: Hydration error occurring
475
+ A: Refer to the "Important Notes" section for hydration problem solutions.
476
+
477
+ #### Q: Performance issues?
478
+ A: Adding too many translations can affect performance. Only add necessary translations.
479
+
480
+ ### Next Steps
481
+
482
+ #### Need more features?
483
+ - [HUA i18n SDK](https://github.com/hua-labs/hua-i18n-sdk): Complete i18n SDK with advanced features
484
+ - [Next.js Internationalization](https://nextjs.org/docs/advanced-features/i18n-routing): Next.js official internationalization
485
+
486
+ #### Community
487
+ - [GitHub Issues](https://github.com/HUA-Labs/HUA-Labs-public/issues): Bug reports and feature requests
488
+ - [Discussions](https://github.com/HUA-Labs/HUA-Labs-public/discussions): Questions and discussions
489
+
490
+ ### License
491
+
492
+ MIT License - Use freely!
493
+
494
+ ### Contributing
495
+
496
+ If you find bugs or have improvement ideas, feel free to contribute anytime!
497
+
498
+ 1. [Fork](https://github.com/HUA-Labs/HUA-Labs-public/fork) this repository
499
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
500
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
501
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
502
+ 5. Open a [Pull Request](https://github.com/HUA-Labs/HUA-Labs-public/pulls)
503
+
504
+ ---
505
+
506
+ **Start internationalization with just one line - start now!**
package/dist/easy.d.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * 진짜 한 줄로 시작하는 다국어 지원
3
+ * 초보자를 위한 최대한 간단한 API
4
+ */
5
+ import React from 'react';
6
+ interface I18nContextType {
7
+ language: string;
8
+ setLanguage: (lang: string) => void;
9
+ t: (key: string) => string;
10
+ translations: Record<string, Record<string, string>>;
11
+ isKorean: boolean;
12
+ isEnglish: boolean;
13
+ toggleLanguage: () => void;
14
+ addTranslation: (lang: string, key: string, value: string) => void;
15
+ getCurrentLanguage: () => string;
16
+ isClient: boolean;
17
+ }
18
+ export declare function SimpleI18n({ children }: {
19
+ children: React.ReactNode;
20
+ }): import("react/jsx-runtime").JSX.Element;
21
+ export declare function useTranslate(): (key: string) => string;
22
+ export declare function useLanguage(): {
23
+ language: string;
24
+ setLanguage: (lang: string) => void;
25
+ isKorean: boolean;
26
+ isEnglish: boolean;
27
+ toggleLanguage: () => void;
28
+ addTranslation: (lang: string, key: string, value: string) => void;
29
+ getCurrentLanguage: () => string;
30
+ };
31
+ export declare function useI18n(): I18nContextType;
32
+ export declare function useSimpleI18n(): {
33
+ t: (key: string) => string;
34
+ toggleLanguage: () => void;
35
+ currentLanguage: string;
36
+ languageName: string;
37
+ languageButtonText: string;
38
+ isClient: boolean;
39
+ addTranslation: (lang: string, key: string, value: string) => void;
40
+ };
41
+ export declare const I18nProvider: typeof SimpleI18n;
42
+ export declare const useTranslation: typeof useTranslate;
43
+ /**
44
+ * TypeScript 파일에서 번역을 로드하는 함수
45
+ * 초보자를 위한 간단한 번역 파일 분리 방법
46
+ */
47
+ export declare function loadTranslationsFromFile(translations: Record<string, Record<string, string>>, addTranslation: (lang: string, key: string, value: string) => void): void;
48
+ /**
49
+ * 번역 파일을 자동으로 로드하는 훅
50
+ * 컴포넌트에서 번역 파일을 쉽게 사용할 수 있게 해줍니다
51
+ */
52
+ export declare function useTranslationsFromFile(translations: Record<string, Record<string, string>>): void;
53
+ export {};
54
+ //# sourceMappingURL=easy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"easy.d.ts","sourceRoot":"","sources":["../src/easy.tsx"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,OAAO,KAAsE,MAAM,OAAO,CAAC;AAiG3F,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAErD,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,kBAAkB,EAAE,MAAM,MAAM,CAAC;IAEjC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAsBD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CA0DrE;AAGD,wBAAgB,YAAY,UA7FjB,MAAM,KAAK,MAAM,CAmG3B;AAED,wBAAgB,WAAW;;wBAtGL,MAAM,KAAK,IAAI;;;0BAMb,IAAI;2BACH,MAAM,OAAO,MAAM,SAAS,MAAM,KAAK,IAAI;8BACxC,MAAM;EA4GjC;AAGD,wBAAgB,OAAO,oBAMtB;AAGD,wBAAgB,aAAa;aA/HlB,MAAM,KAAK,MAAM;0BAKJ,IAAI;;;;;2BACH,MAAM,OAAO,MAAM,SAAS,MAAM,KAAK,IAAI;EA+InE;AAGD,eAAO,MAAM,YAAY,mBAAa,CAAC;AACvC,eAAO,MAAM,cAAc,qBAAe,CAAC;AAI3C;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACpD,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,QAOnE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,QAOrD"}