sheet-i18n 1.5.2 β†’ 1.7.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.
Files changed (2) hide show
  1. package/README.md +322 -290
  2. package/package.json +13 -5
package/README.md CHANGED
@@ -1,156 +1,33 @@
1
- # sheet-i18n
1
+ # sheet-i18n [![npm](https://img.shields.io/npm/v/sheet-i18n)](https://www.npmjs.com/package/sheet-i18n)
2
2
 
3
- **An all-in-one package for sheet-based translation**
3
+ <img src="https://raw.githubusercontent.com/chltjdrhd777/image-hosting/refs/heads/main/sheet-i18n/banner_horizontal_sharp.png" />
4
+
5
+ <br/>
4
6
 
5
- [![npm](https://img.shields.io/npm/v/sheet-i18n)](https://www.npmjs.com/package/sheet-i18n)
6
7
  <a href="https://sheet-i18n.vercel.app/en" target="_blank">
7
8
 
8
9
  <!-- <img height="20px" src="https://img.shields.io/badge/πŸ“š-%20Docs-%23000000"/> -->
9
10
  </a>
10
11
 
11
- ## Installation πŸ› οΈ
12
-
13
- You can install **sheet-i18n** via npm:
14
-
15
- ```bash
16
- npm install sheet-i18n
17
- ```
18
-
19
- ## Usage πŸš€
20
-
21
- ### πŸ“‘ Main Package - `sheet-i18n`
22
-
23
12
  `sheet-i18n` is a **powerful and flexible library** designed to streamline the process of managing and utilizing translations stored in **Google Sheets** _(planned to support other spreadsheets soon)_.
24
13
 
25
14
  It serves as a bridge between your translation data and your application, offering an **end-to-end solution** for exporting, managing, and integrating translations into your projects.
26
15
 
27
16
  The `sheet-i18n` ecosystem is divided into three main packages:
28
17
 
29
- - `sheet-i18n/importer`
30
18
  - `sheet-i18n/react`
31
19
  - `@sheet-i18n/cli`
20
+ - `sheet-i18n/importer`
32
21
 
33
- <br/>
34
-
35
- <details open>
36
- <summary>🌍 Server Export Function - sheet-i18n/importer</summary>
37
-
38
- #### `sheet-i18n/importer`
39
-
40
- The **server-side importer** subpackage allows you to interact with Google Sheets and export translations directly into your project. This is primarily used in server-side environments, such as Next.js API routes or other backend frameworks, where you want to fetch and store translations from a Google Spreadsheet to be served to clients or used within your server application.
41
-
42
- ```jsx
43
- import { googleSheetImporter } from 'sheet-i18n/importer';
44
-
45
- const importer = await googleSheetImporter({
46
- credentials: {
47
- sheetId: 'your-google-sheet-id',
48
- clientEmail: 'your-client-email',
49
- privateKey: 'your-private-key',
50
- },
51
- defaultLocale: 'default-language-in-sheet-header',
52
- });
53
-
54
- await importer.importTranslations();
55
- ```
56
-
57
- ### Configuration βš™οΈ
58
-
59
- The configuration object required for using the importer is as follows:
60
-
61
- #### Required πŸ“
62
-
63
- - **`credentials`**: Google Sheets API credentials:
64
- - `sheetId`: The ID of your Google Spreadsheet (extracted from the URL).
65
- - `clientEmail`: The email of the Google Sheets API client.
66
- - `privateKey`: The private key associated with the client.
67
- - **`defaultLocale`**: The default locale/language specified in your Google Sheet header.
68
-
69
- #### Optional πŸ”§
70
-
71
- - **`headerStartRowNumber`**: Specifies the row number where the headers begin (if not at the top).
72
- - **`ignoredSheets`**: A list of sheets to exclude by title. By default, sheets without the `defaultLocale` in headers will be ignored.
73
- - **`importPath`**: Path to save exported translations from your sheet. This is the location where the exported translations will be saved. By default, it will use the current working directory (cwd). This option is only used when calling the `importTranslations` method.
74
-
75
- ### Importer Methods πŸ› οΈ
76
-
77
- #### `getTranslations` πŸ“
78
-
79
- - **Description**: This function retrieves the translation data, which is structured by locale keys (such as "ko", "en", etc.). It collects all translations from the specified sheet, replaces any placeholders, and prepares them to be sent to the client in the response body. Each key corresponds to a language, and the value for each key is an object containing the translated text for that locale.
80
-
81
- - **Type**: Function
82
- - **Parameters**: None
83
- - **Returns**: An object where each key is a locale (e.g., "ko", "en"), and the value is the respective translation data for that locale.
84
-
85
- #### Example:
86
-
87
- If the headers in your Google Sheets are `["ko", "en", ...]`, the result returned by `getTranslations` will look like this:
88
-
89
- ```ts
90
- {
91
- "ko": {
92
- "greeting": "μ•ˆλ…•ν•˜μ„Έμš”",
93
- "farewell": "μ•ˆλ…•νžˆ κ°€μ„Έμš”"
94
- },
95
- "en": {
96
- "greeting": "Hello",
97
- "farewell": "Goodbye"
98
- }
99
-
100
- ...
101
- }
102
- ```
103
-
104
- In this example:
105
-
106
- - `"ko"` contains the translations for Korean.
107
- - `"en"` contains the translations for English.
108
- Each locale’s object contains key-value pairs for individual translations.
109
-
110
- #### `importTranslations` πŸ“€
111
-
112
- - **Description**: This asynchronous function is used in a Node.js environment to export translations directly into your project. It is especially useful if your project includes server-side APIs (like Next.js API routes) and you need to update the locale JSON data in your project. It can be invoked to update or create the locale files within your project, ensuring that the translation data is synced with the local environment.
113
-
114
- - **Type**: Function
115
- - **Parameters**: None
116
- - **Returns**: `void`
117
-
118
- #### Example:
119
-
120
- If you call the `importTranslations` function, it will update or create JSON files in your project for each locale. The result could look like this:
22
+ ### Installation
121
23
 
122
- ```ts
123
- // ko.json
124
- {
125
- "greeting": "μ•ˆλ…•ν•˜μ„Έμš”",
126
- "farewell": "μ•ˆλ…•νžˆ κ°€μ„Έμš”"
127
- }
128
-
129
- // en.json
130
- {
131
- "greeting": "Hello",
132
- "farewell": "Goodbye"
133
- }
24
+ ```shell
25
+ npm install sheet-i18n
26
+ npm install @sheet-i18n/cli -D
134
27
  ```
135
28
 
136
- ### API Documentation πŸ“š
137
-
138
- This package provides a streamlined way to export data using sheets API. It is designed to simplify the integration of spreadsheet data into your applications, particularly for translation workflows and internationalization (i18n).
139
-
140
- [Google Sheets API Documentation](https://developers.google.com/sheets/api)<br>
141
- [Google Auth Library](https://www.npmjs.com/package/google-auth-library)<br>
142
- [Google Spreadsheet](https://www.npmjs.com/package/google-spreadsheet)
143
-
144
- ### Exporting Data Format πŸ—‚οΈ
145
-
146
- The exported translations will be saved in a format that is easy to use for localization purposes. Each translation is stored in its respective locale folder, with a structured format.
147
-
148
- </details>
149
-
150
- ---
151
-
152
- <details>
153
- <summary>βš›οΈ Frontend Translation Provider - sheet-i18n/react</summary>
29
+ <details open>
30
+ <summary><strong>βš›οΈ Frontend Translation Provider - sheet-i18n/react</strong></summary>
154
31
 
155
32
  ### `@sheet-i18n/react`
156
33
 
@@ -160,17 +37,20 @@ This package provides tools to handle translations in React applications using c
160
37
 
161
38
  ## ✨ Package Introduction
162
39
 
163
- - **`I18nStore`**: _Store Creation Class_ for managing translation data.
40
+ - **`I18nStore`**: _Core Store Creation Class_ for managing translation data.
164
41
  - **`createI18nContext`**: _React Context_ to generate providers and hooks for translation.
165
42
  - **`IntlProvider`**: _React Translation Provider_ for managing current locale.
166
43
  - **`useTranslation`**: _Client Side Translation Hook_ for easy access to translation messages on the client side.
167
44
  - **`getTranslation`**: _Static Translation Function_ for easy access to translation messages on Static module files.
168
45
 
169
- ## πŸš€ Getting Started
46
+ ## πŸš€ Getting Started(Manually)
170
47
 
171
- ### Basic Usage
48
+ > ⚑ **Strongly recommended to use the init CLI for setup**
49
+ > πŸ‘‰ [Please follow the Init CLI section](#initial-setup-anchor)
50
+ >
51
+ > If you don't want to use the CLI, you can follow the `Manual Setup` below.
172
52
 
173
- #### 1. Define Translation Data
53
+ ### step 1. Define Translation Data
174
54
 
175
55
  Prepare locale JSON files:
176
56
 
@@ -192,13 +72,13 @@ Prepare locale JSON files:
192
72
  }
193
73
  ```
194
74
 
195
- #### 2. Initialize i18nStore
75
+ ### step 2. Initialize i18nStore
196
76
 
197
77
  this store will be used as a core translations module.
198
78
 
199
79
  ```tsx
200
- import en from './en.json';
201
80
  import ko from './ko.json';
81
+ import en from './en.json';
202
82
 
203
83
  import { I18nStore } from '@sheet-i18n/react';
204
84
 
@@ -216,11 +96,13 @@ export const i18nStore = new I18nStore({
216
96
  // dynamicLoaders: {
217
97
  // ko: () => import('./ko.json'),
218
98
  // en: () => import('./en.json'),
99
+ // jp: () => import('./jp.json'),
100
+ // cn: () => import('./cn.json'),
219
101
  // },
220
102
  });
221
103
  ```
222
104
 
223
- #### 3. Create i18n Context
105
+ ### step 3. Create i18n Context
224
106
 
225
107
  ```tsx
226
108
  import { i18nStore } from './file-path-of-i18nStore-initiated';
@@ -230,22 +112,24 @@ export const { IntlProvider, useTranslation, getTranslation } =
230
112
  createI18nContext(i18nStore);
231
113
  ```
232
114
 
233
- #### 4. Mount Intl Context Provider in your App
115
+ ### step 4. Mount Intl Context Provider in your App
234
116
 
235
117
  ```tsx
236
118
  import React from 'react';
237
119
  import { IntlProvider } from './i18nContext';
238
120
 
239
121
  const App = () => {
122
+ const [locale, setLocale] = useState('en');
123
+
240
124
  return (
241
- <IntlProvider>
125
+ <IntlProvider currentLocale={locale}>
242
126
  <YourComponent />
243
127
  </IntlProvider>
244
128
  );
245
129
  };
246
130
  ```
247
131
 
248
- #### 5. Use Translations
132
+ ### step 5. Use Translations
249
133
 
250
134
  ```tsx
251
135
  import React from 'react';
@@ -269,27 +153,28 @@ const YourComponent = () => {
269
153
 
270
154
  ### `I18nStore(core)`
271
155
 
272
- The `I18nStore` manages type-safe translation states, ensuring consistency across locales.
156
+ The `I18nStore` manages translation states, ensuring consistency across locales.
273
157
 
274
158
  #### Parameters:
275
159
 
276
- - **`supportedLocales`**: Array of supported locale strings.
277
- <br/>
278
- <br/>
279
- - **`defaultLocale`**: The default locale, included in `supportedLocales`.
280
- <br/>
281
- <br/>
282
- - **`localeSet(optional. choice 1)`**: An object where keys match `supportedLocales`, and values are translation sets. If you want to use this option, you need to provide all static locale data according to the `supportedLocales`.
283
- <br/>
284
- <br/>
285
- - **`dynamicLoaders(optional. choice 2)`**: An object where keys match `supportedLocales`, and values are dynamic translation loader functions.
286
- <br/>
287
- <br/>
288
- - **`typeSafe(optional, default = false)`**: An optional boolean indicating whether to use type-safe translations.
160
+ ### 🧠 I18nStore Configuration Options
161
+
162
+ | Option | Type | Required | Description |
163
+ | ------------------ | ---------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- |
164
+ | `supportedLocales` | string[] | βœ… | List of supported locale codes. |
165
+ | `defaultLocale` | string | βœ… | Default locale to use when no match is found. Must be included in `supportedLocales`. |
166
+ | localeSet | Record<string, object> | | _(Static Loading Option)_ Preload all translation data for each locale in memory. Keys must match `supportedLocales`. |
167
+ | dynamicLoaders | Record<string, () => Promise<any>> | | _(Recommended for large locale sets)_ Dynamically load translation data on demand, reducing initial bundle size. |
168
+ | typeSafe | boolean | | Enable strict key checking and autocompletion (default: `false`). |
289
169
 
290
170
  > πŸ’‘ **typeSafe?** <br/>
291
171
  > I18nStore doesn't enforce adherence to your locale JSON definitions by default. This means that you can add translation data even if it isn’t pre-defined in your locale JSON files. However, if you prefer to enforce strict type-safety, you can manually enable the typeSafe option which allows you to notice the auto-completed list in translation data.
292
172
  >
173
+ > But to enable correct type checking, `the full localeSet must be defined according to the
174
+ supportedLocales in i18nStore`
175
+ >
176
+ > As a result, type auto-completion relies on having the complete localeSet defined at initialization. This means that using dynamicLoaders to fetch locales conditionally at runtime can be limiting when strict type-safety is enabled.
177
+ >
293
178
  > ```tsx
294
179
  > // typeSafe: true
295
180
  > const YourComponent = () => {
@@ -304,16 +189,54 @@ The `I18nStore` manages type-safe translation states, ensuring consistency acros
304
189
  > );
305
190
  > };
306
191
  > ```
307
-
192
+ >
308
193
  > ⚠️ Caveats:
309
194
  >
310
195
  > 1. `supportedLocales` must be an array of locale strings.
311
196
  > 2. `defaultLocale` must exist in `supportedLocales`.
312
- > 3. `localeSet` must be an object with keys matching `supportedLocales`.
197
+
198
+ ### πŸš€ Static vs Dynamic Loading
199
+
200
+ You can configure how translations are loaded:
201
+
202
+ - **Static (`localeSet`)**
203
+ Load all translations at once. Ideal for small projects or limited locale sets.
204
+
205
+ - **Dynamic (`dynamicLoaders`)** βœ… _Recommended_
206
+ Load only the locale needed, reducing the bundle size dramatically.
207
+ Useful when supporting many languages or large translation files.
208
+
209
+ ```ts
210
+ export const i18nStore = new I18nStore({
211
+ supportedLocales: ['en', 'fr', 'ko'],
212
+ defaultLocale: 'en',
213
+ dynamicLoaders: {
214
+ en: () => import('./en.json'),
215
+ fr: () => import('./fr.json'),
216
+ ko: () => import('./ko.json'),
217
+ },
218
+ });
219
+ ```
220
+
221
+ πŸ’‘ When both `localeSet` and `dynamicLoaders` are defined, sheet-i18n **automatically merges** both sources β€” static data loads immediately, while dynamic data supplements on-demand.
222
+
223
+ ---
224
+
225
+ ### 🎯 Why Dynamic Loaders?
226
+
227
+ For projects with many locale datasets, it's often preferable to load translation data on demand rather than all at once. It is better using `dynamicLoaders` to enable this conditional loading strategy.
228
+
229
+ - βœ… Reduces the initial JavaScript bundle size.
230
+ - βœ… Keeps only required locales in memory.
231
+ - βœ… Works well with code-splitting and SSR/CSR.
232
+ - βœ… Enables **lazy-loading** for translations.
313
233
 
314
234
  #### Example:
315
235
 
316
236
  ```tsx
237
+ import ko from './locales/ko.json';
238
+ import en from './locales/en.json';
239
+
317
240
  export const i18nStore = new I18nStore({
318
241
  supportedLocales: ['ko', 'en'],
319
242
  defaultLocale: 'ko',
@@ -327,6 +250,8 @@ export const i18nStore = new I18nStore({
327
250
  // dynamicLoaders: {
328
251
  // ko: () => import('./ko.json'),
329
252
  // en: () => import('./en.json'),
253
+ // jp: () => import('./jp.json'),
254
+ // cn: () => import('./cn.json'),
330
255
  // },
331
256
  });
332
257
  ```
@@ -360,7 +285,7 @@ A Context provider to provide translations to child components.
360
285
 
361
286
  - A key representing the current locale to use for translations.
362
287
  - If not provided, the user's preferred language is automatically detected based on the browser setting.
363
- - The fallback is the default locale in **i18nStore** if the detected language is unsupported.
288
+ - The fallback is the default locale in **i18nStore** if the detected user-preferred language is not unsupported in the `supportedLocales`.
364
289
 
365
290
  - **`children`**: React children.
366
291
 
@@ -496,7 +421,7 @@ It provide two possible supports
496
421
 
497
422
  #### **βœ… Usage Scenarios**
498
423
 
499
- #### **Scenario 1: Context where the translation value is evaluated at runtime**
424
+ #### **[Scenario 1]: Context where the call expression of `t` function is evaluated at runtime**
500
425
 
501
426
  - For the common example, **t** call expression in a **function module**
502
427
  - This behaves the same as `useTranslation`'s `t` function.
@@ -524,7 +449,7 @@ export default function App() {
524
449
 
525
450
  **Result:** The translation is resolved **immediately** during runtime.
526
451
 
527
- #### **⚠️ Scenario 2: Context where the translation value is evaluated immediately**
452
+ #### **[Scenario 2]: Context where the translation value is evaluated immediately**
528
453
 
529
454
  - If the module is **imported dynamically in a client-side component**, the evaluation order of `getTranslation` and `t` call expression may not be guaranteed.
530
455
  - Since JavaScript **evaluates modules at import time**, it may attempt to access translation values before `IntlProvider` has fully initialized the locale.
@@ -560,39 +485,15 @@ export default function App() {
560
485
  }
561
486
  ```
562
487
 
563
- ## πŸ›  Error Handling
564
-
565
- Custom error messages help identify misconfigurations:
566
-
567
- 1. **Invalid Params**: Ensure `supportedLocales`, `defaultLocale`, and `localeSet` are correctly provided.
568
- 2. **Missing Default Locale**: The `defaultLocale` must exist in `supportedLocales`.
569
- 3. **Invalid LocaleSet**: Ensure the `localeSet` keys match `supportedLocales`.
570
-
571
- ## πŸ“œ Library Versions πŸ”’
572
-
573
- This package supports the following library versions:
574
-
575
- - **React**: `^19.0.0`
576
- - **React Intl**: `^7.0.4`
577
-
578
- ## πŸ“œ License
579
-
580
- This project is licensed under the ISC License.
581
-
582
- ## πŸ‘€ Author
583
-
584
- **devAnderson**
585
- [GitHub](https://github.com/chltjdrhd777)
586
- [chltjdrhd777@gmail.com](mailto:chltjdrhd777@gmail.com)
587
-
588
488
  </details>
589
489
 
590
490
  ---
591
491
 
592
- <details>
593
- <summary>πŸ”§ CLI for Automated Translation Management - @sheet-i18n/cli</summary>
492
+ <details open>
493
+ <summary><strong>
494
+ πŸ”§ CLI for easy bidirectional syncing - @sheet-i18n/cli</strong></summary>
594
495
 
595
- #### @sheet-i18n/cli
496
+ ### `@sheet-i18n/cli`
596
497
 
597
498
  A CLI tool for efficient translation management using Google Sheets, with a focus on developer experience (DX).
598
499
 
@@ -605,7 +506,7 @@ A CLI tool for efficient translation management using Google Sheets, with a focu
605
506
 
606
507
  ## Core Concepts 🌟
607
508
 
608
- ### 😭 Traditional Translation Workflow
509
+ ### 😭 General Translation Workflow
609
510
 
610
511
  The traditional process of managing translations with Google Spreadsheets often includes these steps:
611
512
 
@@ -631,78 +532,80 @@ This CLI streamlines the process by shifting the focus to developers:
631
532
 
632
533
  With this approach, unnecessary back-and-forth is eliminated, and translations align seamlessly with code.
633
534
 
634
- ## PreRequisite πŸ“
535
+ ## πŸš€ Initial Setup with CLI
635
536
 
636
- This library is tightly integrated with the @sheet-i18n/react package, which provides the React components needed for rendering translations efficiently. As a result, you must set up **`@sheet-i18n/react`** in your project before using this CLI.
537
+ <a id="initial-setup-anchor"></a>
637
538
 
638
- #### 1. Initialize i18n Store
539
+ `@sheet-i18n/cli` provides a fully automated setup for React applications.
540
+ Once installed, you can bootstrap the required i18n context, store, and folder structure by simply running:
639
541
 
640
- This store will be used as a core translations module.
542
+ ```bash
543
+ npx sheet-i18n init
544
+ ```
641
545
 
642
- ```tsx
643
- import en from './en.json';
644
- import ko from './ko.json';
546
+ This will automatically generate:
645
547
 
646
- import { I18nStore } from '@sheet-i18n/react';
548
+ - A preconfigured `i18nStore` using `@sheet-i18n/react`
549
+ - A ready-to-use `i18nContext.ts` that exports `IntlProvider`, `useTranslation`, and `getTranslation`
550
+ - Example locale JSON files (e.g., `en.json`, `ko.json`)
551
+ - The `sheet.config.json` file for managing your CLI behavior and Google Sheets credentials
647
552
 
648
- export const i18nStore = new I18nStore({
649
- supportedLocales: ['ko', 'en'],
650
- defaultLocale: 'ko',
651
- localeSet: {
652
- ko,
653
- en,
654
- },
655
- typeSafe: false, // optional (default: true)
656
- });
657
- ```
553
+ > πŸ’‘ All files will be created in the recommended structure (e.g. `src/i18n`, `src/locales`), and safely skipped if they already exist.
658
554
 
659
- > πŸ’‘ **typeSafe?** <br/>
660
- > I18nStore doesn't enforce adherence to your locale JSON definitions by default. This means that you can add translation data even if it isn’t pre-defined in your locale JSON files. However, if you prefer to enforce strict type-safety, you can manually enable the typeSafe option which allows you to notice the auto-completed list in translation data.
661
- >
662
- > ```tsx
663
- > // typeSafe: true
664
- > const YourComponent = () => {
665
- > // "useTranslation" shows the autocompletion suggestions
666
- > const { t } = useTranslation('header');
667
- >
668
- > return (
669
- > <div>
670
- > {/* "t" function shows the autocompletion suggestions */}
671
- > <button>{t('login')}</button>
672
- > </div>
673
- > );
674
- > };
675
- > ```
555
+ ---
676
556
 
677
- #### 2. Create i18n Context
557
+ ### βœ… What You No Longer Have to Do Manually
678
558
 
679
- ```tsx
680
- import { i18nStore } from './file-path-of-i18nStore-initiated';
681
- import { createI18nContext } from '@sheet-i18n/react';
559
+ - You don’t need to manually initiate `I18nStore` or set up the React context.
560
+ - You don’t need to manually prepare locale JSON templates.
561
+ - You don’t need to manually configure `sheet.config.json`.
682
562
 
683
- export const { IntlProvider, useTranslation } = createI18nContext(i18nStore);
563
+ Just run the init command and you’re ready to use `useTranslation()` in your components.
564
+
565
+ ---
566
+
567
+ ### πŸ—‚οΈ Example Output:
568
+
569
+ ```bash
570
+ πŸ“¦ your-project/
571
+ β”œβ”€β”€ πŸ“„ .gitignore # Automatically appends 'sheet.config.json' to ignore list
572
+ β”œβ”€β”€ πŸ“„ sheet.config.json # CLI configuration file (contains Google Sheet credentials & options)
573
+ └── πŸ“ src/
574
+ └── πŸ“ i18n/
575
+ β”œβ”€β”€ πŸ“„ i18nContext.tsx # React context for IntlProvider, useTranslation, and getTranslation
576
+ β”œβ”€β”€ πŸ“„ i18nStore.ts # Initializes I18nStore with supported locales and translation data
577
+ β”œβ”€β”€ πŸ“„ en.json # Placeholder for English translation strings
578
+ └── πŸ“„ ko.json # Placeholder for Korean translation strings
684
579
  ```
685
580
 
686
- #### 3. Mount Intl Context Provider in your App
581
+ βœ… The CLI automatically creates this structure after running `npx sheet-i18n init`.
582
+ πŸ›‘οΈ If `sheet.config.json` or `src/i18n` already exist, the CLI will skip the creation of these files.
583
+
584
+ after running `npx sheet-i18n init`, you can mount the IntlProvider in your app.
585
+
586
+ #### Mount Intl Context Provider in your App
687
587
 
688
588
  ```tsx
689
589
  import React from 'react';
690
- import { IntlProvider } from './i18nContext';
590
+ import I18nContextProvider from './i18n/i18nContext';
691
591
 
692
592
  const App = () => {
593
+ const [locale, setLocale] = useState('en');
594
+
693
595
  return (
694
- <IntlProvider>
596
+ <I18nContextProvider currentLocale={locale}>
695
597
  <YourComponent />
696
- </IntlProvider>
598
+ </I18nContextProvider>
697
599
  );
698
600
  };
699
601
  ```
700
602
 
701
- #### 4. Use Translations
603
+ #### Use Translations
702
604
 
703
605
  ```tsx
606
+ // YourComponent.tsx
704
607
  import React from 'react';
705
- import { useTranslation } from './i18nContext';
608
+ import { useTranslation } from './i18n/i18nContext';
706
609
 
707
610
  const YourComponent = () => {
708
611
  const { t } = useTranslation('header');
@@ -716,31 +619,11 @@ const YourComponent = () => {
716
619
  };
717
620
  ```
718
621
 
719
- Follow the documentation for @sheet-i18n/react to ensure proper configuration.
720
-
721
- ## Base workflow
722
-
723
- Install the CLI tool globally or as a dev dependency:
622
+ ### That's it! <br/>
724
623
 
725
- ```shell
726
- npm install -g @sheet-i18n/cli
727
- ```
728
-
729
- or
730
-
731
- ```shell
732
- npm install --save-dev @sheet-i18n/cli
733
- ```
734
-
735
- Initialize the CLI in your project:
736
-
737
- ```shell
738
- npx sheet-i18n init
739
- ```
624
+ your translations are now ready to use in your application.
740
625
 
741
- After initialization, the **"sheet.config.json"** file will be created in the root of your project (and .gitignored automatically).
742
-
743
- ### Configuration βš™οΈ
626
+ ### βš™οΈ sheet.config.json
744
627
 
745
628
  The CLI requires a `sheet.config.json` file in the root of your project. Run `sheet-i18n init` to generate this file automatically.
746
629
 
@@ -760,26 +643,38 @@ Example `sheet.config.json`:
760
643
  "defaultLocale": "en",
761
644
  "supportedLocales": ["en", "fr", "es"],
762
645
  "ignoredSheets": ["BASE"],
763
- "importPath": "./src/locales"
646
+ "importPath": "./src/locales",
647
+ "autoAppendFilePathColumn": {
648
+ "enabled": true,
649
+ "columnName": "__filePath",
650
+ "fullFilePath": false
651
+ }
764
652
  }
765
653
  }
766
654
  ```
767
655
 
768
- #### 1. File change monitoring configuration
656
+ ### 1. File change monitoring configuration
657
+
658
+ | Option | Type | Required | Default | Description |
659
+ | ------------------ | -------- | -------- | -------------------------- | ------------------------------------------------------------------------------ |
660
+ | `watchEntry` | string | | "src" | Entry path to monitor file changes, relative to the current working directory. |
661
+ | `detectExtensions` | string[] | | ["jsx", "js", "tsx", "ts"] | List of file extensions to watch. |
769
662
 
770
- - `watchEntry` (optional): Entry path to detect file changes relative to current working directory (default: `src`)
771
- - `detectExtensions` (optional): File extensions to monitor (default: `jsx`, `js`, `tsx`, `ts`).
663
+ ### 2. Register command configuration
772
664
 
773
- #### 2. Register command configuration
665
+ ### πŸ“„ `googleSheetConfig` Options
774
666
 
775
- - **`googleSheetConfig (required)`**: Configuration for Google Sheets integration:
776
- - **`spreadsheetId (required)`**: The ID of your Google Spreadsheet.
777
- - **`credentials (required)`**: Contains `sheetId`, `clientEmail`, and `privateKey` for API authentication.
778
- - **`defaultLocale (required)`**: Default language/locale used in the sheet header.
779
- - **`supportedLocales(required)`**: List of locales supported in your sheet (default: [defaultLocale]).
780
- - **headerStartRowNumber** (optional): Row number where headers start (default: 1).
781
- - **ignoredSheets** (optional): Titles of sheets to exclude from the translation process.
782
- - **importPath** (optional): Directory path to save exported translations based on the current working directory (default: `.`).
667
+ | Option | Type | Required | Default | Description |
668
+ | -------------------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
669
+ | `credentials.sheetId` | string | βœ… | | The same ID as `spreadsheetId` (for API auth). |
670
+ | `credentials.clientEmail` | string | βœ… | | Client email from your Google Service Account credentials. |
671
+ | `credentials.privateKey` | string | βœ… | | Private key from your Google Service Account credentials. |
672
+ | `defaultLocale` | string | βœ… | | The default language/locale used in the sheet's header row. |
673
+ | `supportedLocales` | string[] | βœ… | | Array of all supported locale codes (e.g., `["en", "ko"]`). |
674
+ | `headerStartRowNumber` | number | | 1 | Row number where sheet headers begin. |
675
+ | `ignoredSheets` | string[] | | | Titles of sheets to ignore during register/import (e.g., `["BASE"]`). |
676
+ | `importPath` | string | | current working directory | Directory path to export translation JSON files. |
677
+ | `autoAppendFilePathColumn` | object | | <strong>enabled: </strong>true<br/><strong>columnName: </strong>"\_\_filePath"<br/><strong>fullFilePath:</strong>false | Configuration for appending reference file path to each translation row. This indicates where the translation key is located in your source code.<br><br>- `enabled`: Whether to append the file path column<br>- `columnName`: Column name to use for file path<br>- `fullFilePath`: Show full path or mask intermediate folders (e.g., `"*******/folder1/folder2/file.ts"`) |
783
678
 
784
679
  ## Commands
785
680
 
@@ -829,13 +724,18 @@ function Component (){
829
724
  }
830
725
  ```
831
726
 
832
- The _watch result_ is
727
+ The _watched result_ is
833
728
 
834
729
  ```shell
835
- πŸ“ Translations Store:
836
- {
837
- environment: Set(1) { 'over', 'under' }
838
- }
730
+ Detected Translations:
731
+
732
+ πŸ“„ [Sheet Title]: environment
733
+ - over
734
+ - under
735
+
736
+ # You can proceed using the shortcuts below:
737
+ - Press <Shift + R> to register the detected changes.
738
+ - Press <Ctrl + C> to cancel the watch command.
839
739
  ```
840
740
 
841
741
  </br>
@@ -843,7 +743,7 @@ The _watch result_ is
843
743
  ### πŸ“€ register
844
744
 
845
745
  ```shell
846
- sheet-i18n register [options]
746
+ npx sheet-i18n register [options]
847
747
  ```
848
748
 
849
749
  Registers translation data to Google Sheets.
@@ -860,15 +760,18 @@ Registers translation data to Google Sheets.
860
760
 
861
761
  - `-s, --scope <scope>`
862
762
  Define the scope of the registration process:
763
+
863
764
  - **`diff`**: Only scans translation keys that have been modified in the Git history (based on `git diff`).
864
- - **`total`**: Scans the entire directory for all translation keys and updates the spreadsheet, regardless of Git changes.
865
- **Default**: `diff`
765
+ - **`total`**: Scans the entire directory for all translation keys and updates the spreadsheet, regardless of Git changes.
766
+ - **`select`**: User selection mode which allows you to choose the sheets to register.
767
+
768
+ - **Default**: `diff`
866
769
 
867
770
  ---
868
771
 
869
- #### Detailed description of the `scope` option:
772
+ #### πŸ“„ Detailed description of the `scope` option:
870
773
 
871
- ##### Scope: `diff`
774
+ #### Scope: `diff`
872
775
 
873
776
  - The CLI identifies changes in translation keys by comparing the current state of the codebase with the latest Git commit.
874
777
  - It only processes translation keys added, removed, or modified since the last commit.
@@ -881,9 +784,7 @@ Registers translation data to Google Sheets.
881
784
  npx sheet-i18n register
882
785
  ```
883
786
 
884
- ---
885
-
886
- ##### Scope: `total`
787
+ #### Scope: `total`
887
788
 
888
789
  - The CLI scans the entire specified directory for all translation keys from the directory path you provide.
889
790
  - This is useful for full synchronization, ensuring all keys are registered in the spreadsheet.
@@ -892,7 +793,23 @@ npx sheet-i18n register
892
793
  ##### Example:
893
794
 
894
795
  ```shell
895
- sheet-i18n register --scope total
796
+ npx sheet-i18n register --scope total
797
+ ```
798
+
799
+ #### Scope: `select`
800
+
801
+ - The CLI prompts you to manually select which sheets you want to update.
802
+
803
+ - Once the selection is made, only the chosen sheets will have their translation data updated in the Google Spreadsheet.
804
+
805
+ - This mode is especially useful for partial updates, allowing you to skip scanning the entire directory and focus on specific sheets.
806
+
807
+ - It’s also helpful in cases where you’ve committed changes without registering translation data during development β€” instead of syncing all translations, you can update only the relevant sheets as needed.
808
+
809
+ ##### Example:
810
+
811
+ ```shell
812
+ npx sheet-i18n register --scope select
896
813
  ```
897
814
 
898
815
  </br>
@@ -921,8 +838,125 @@ The configuration of export command is based on **`sheet.config.json`** on your
921
838
  }
922
839
  ```
923
840
 
841
+ </details>
842
+
924
843
  ---
925
844
 
845
+ <details open>
846
+ <summary><strong>🌍 Server Export Function - sheet-i18n/importer</strong></summary>
847
+
848
+ ### `sheet-i18n/importer`
849
+
850
+ The **server-side importer** subpackage allows you to interact with Google Sheets and export translations directly into your project. This is primarily used in server-side environments, such as Next.js API routes or other backend frameworks, where you want to fetch and store translations from a Google Spreadsheet to be served to clients or used within your server application.
851
+
852
+ ```jsx
853
+ import { googleSheetImporter } from 'sheet-i18n/importer';
854
+
855
+ const importer = await googleSheetImporter({
856
+ credentials: {
857
+ sheetId: 'your-google-sheet-id',
858
+ clientEmail: 'your-client-email',
859
+ privateKey: 'your-private-key',
860
+ },
861
+ defaultLocale: 'default-language-in-sheet-header',
862
+ });
863
+
864
+ await importer.importTranslations();
865
+ ```
866
+
867
+ ### Configuration βš™οΈ
868
+
869
+ The configuration object required for using the importer is as follows:
870
+
871
+ #### Required πŸ“
872
+
873
+ - **`credentials`**: Google Sheets API credentials:
874
+ - `sheetId`: The ID of your Google Spreadsheet (extracted from the URL).
875
+ - `clientEmail`: The email of the Google Sheets API client.
876
+ - `privateKey`: The private key associated with the client.
877
+ - **`defaultLocale`**: The default locale/language specified in your Google Sheet header.
878
+
879
+ #### Optional πŸ”§
880
+
881
+ - **`headerStartRowNumber`**: Specifies the row number where the headers begin (if not at the top).
882
+ - **`ignoredSheets`**: A list of sheets to exclude by title. By default, sheets without the `defaultLocale` in headers will be ignored.
883
+ - **`importPath`**: Path to save exported translations from your sheet. This is the location where the exported translations will be saved. By default, it will use the current working directory (cwd). This option is only used when calling the `importTranslations` method.
884
+
885
+ ### Importer Methods πŸ› οΈ
886
+
887
+ #### `getTranslations` πŸ“
888
+
889
+ - **Description**: This function retrieves the translation data, which is structured by locale keys (such as "ko", "en", etc.). It collects all translations from the specified sheet, replaces any placeholders, and prepares them to be sent to the client in the response body. Each key corresponds to a language, and the value for each key is an object containing the translated text for that locale.
890
+
891
+ - **Type**: Function
892
+ - **Parameters**: None
893
+ - **Returns**: An object where each key is a locale (e.g., "ko", "en"), and the value is the respective translation data for that locale.
894
+
895
+ #### Example:
896
+
897
+ If the headers in your Google Sheets are `["ko", "en", ...]`, the result returned by `getTranslations` will look like this:
898
+
899
+ ```ts
900
+ {
901
+ "ko": {
902
+ "greeting": "μ•ˆλ…•ν•˜μ„Έμš”",
903
+ "farewell": "μ•ˆλ…•νžˆ κ°€μ„Έμš”"
904
+ },
905
+ "en": {
906
+ "greeting": "Hello",
907
+ "farewell": "Goodbye"
908
+ }
909
+
910
+ ...
911
+ }
912
+ ```
913
+
914
+ In this example:
915
+
916
+ - `"ko"` contains the translations for Korean.
917
+ - `"en"` contains the translations for English.
918
+ Each locale’s object contains key-value pairs for individual translations.
919
+
920
+ #### `importTranslations` πŸ“€
921
+
922
+ - **Description**: This asynchronous function is used in a Node.js environment to export translations directly into your project. It is especially useful if your project includes server-side APIs (like Next.js API routes) and you need to update the locale JSON data in your project. It can be invoked to update or create the locale files within your project, ensuring that the translation data is synced with the local environment.
923
+
924
+ - **Type**: Function
925
+ - **Parameters**: None
926
+ - **Returns**: `void`
927
+
928
+ #### Example:
929
+
930
+ If you call the `importTranslations` function, it will update or create JSON files in your project for each locale. The result could look like this:
931
+
932
+ ```ts
933
+ // ko.json
934
+ {
935
+ "greeting": "μ•ˆλ…•ν•˜μ„Έμš”",
936
+ "farewell": "μ•ˆλ…•νžˆ κ°€μ„Έμš”"
937
+ }
938
+
939
+ // en.json
940
+ {
941
+ "greeting": "Hello",
942
+ "farewell": "Goodbye"
943
+ }
944
+ ```
945
+
946
+ ### API Documentation πŸ“š
947
+
948
+ This package provides a streamlined way to export data using sheets API. It is designed to simplify the integration of spreadsheet data into your applications, particularly for translation workflows and internationalization (i18n).
949
+
950
+ [Google Sheets API Documentation](https://developers.google.com/sheets/api)<br>
951
+ [Google Auth Library](https://www.npmjs.com/package/google-auth-library)<br>
952
+ [Google Spreadsheet](https://www.npmjs.com/package/google-spreadsheet)
953
+
954
+ ### Exported Data Format πŸ—‚οΈ
955
+
956
+ The exported translations will be saved in a format that is easy to use for localization purposes. Each translation is stored in its respective locale folder, with a structured format.
957
+
958
+ </details>
959
+
926
960
  ## License πŸ“œ
927
961
 
928
962
  This project is licensed under the ISC License. See the LICENSE file for details.
@@ -930,5 +964,3 @@ This project is licensed under the ISC License. See the LICENSE file for details
930
964
  ## Author ✍️
931
965
 
932
966
  Created by [devAnderson](https://github.com/chltjdrhd777).
933
-
934
- </details>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sheet-i18n",
3
- "version": "1.5.2",
3
+ "version": "1.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/chltjdrhd777/sheet-i18n"
@@ -27,7 +27,14 @@
27
27
  "sheet-i18n",
28
28
  "spreadsheet",
29
29
  "i18n",
30
- "translation"
30
+ "translation",
31
+ "internationalization",
32
+ "localization",
33
+ "i18n workflow",
34
+ "spreadsheet i18n",
35
+ "i18n management",
36
+ "translation management",
37
+ "google spreadsheet"
31
38
  ],
32
39
  "author": {
33
40
  "name": "devAnderson",
@@ -35,14 +42,15 @@
35
42
  "url": "https://github.com/chltjdrhd777"
36
43
  },
37
44
  "license": "ISC",
45
+ "homepage": "https://github.com/chltjdrhd777/sheet-i18n",
38
46
  "dependencies": {
39
- "@sheet-i18n/importer": "1.5.2",
40
- "@sheet-i18n/react": "1.2.0"
47
+ "@sheet-i18n/importer": "1.7.0",
48
+ "@sheet-i18n/react": "1.4.0"
41
49
  },
42
50
  "devDependencies": {
43
51
  "tsup": "^6.0.0",
44
52
  "typescript": "^5.0.0",
45
- "@sheet-i18n/typescript-config": "1.5.0"
53
+ "@sheet-i18n/typescript-config": "1.7.0"
46
54
  },
47
55
  "scripts": {
48
56
  "build": "tsup",