Skip to content

Commit

Permalink
feat: add disablePageLocales and localeRoutes
Browse files Browse the repository at this point in the history
  • Loading branch information
s00d committed Aug 31, 2024
1 parent 68e3212 commit 59d1efe
Show file tree
Hide file tree
Showing 20 changed files with 15,487 additions and 4,069 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ Temporary Items
.apdisk
test-results
docs/.vitepress/cache
artillery-output.json
1 change: 0 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"name": "@nuxtjs/i18n-client",
"private": true,
"devDependencies": {
"@nuxt/devtools-ui-kit": "latest",
"json-editor-vue": "^0.15.2"
}
}
2 changes: 2 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export default defineConfig({
{ text: 'Migration', link: '/guide/migration' },
{ text: 'Contribution', link: '/guide/contribution' },
{ text: 'Multi Domain Locales', link: '/guide/multi-domain-locales' },
{ text: 'Custom Localized Routes', link: '/guide/custom-locale-routes' },
],
},
{
Expand Down Expand Up @@ -88,6 +89,7 @@ export default defineConfig({
{ text: 'Migration', link: '/migration' },
{ text: 'Contribution', link: '/contribution' },
{ text: 'Multi Domain Locales', link: '/multi-domain-locales' },
{ text: 'Custom Localized Routes', link: '/custom-locale-routes' },
],
},
],
Expand Down
41 changes: 36 additions & 5 deletions docs/api/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,44 @@ $mergeTranslations({
})
```

## 🚦 `$defineI18nRoute(routeDefinition: { locales?: string[] | Record<string, Record<string, TranslationObject>> })`
Here's the updated documentation for the `$defineI18nRoute` function with the added description for the `localeRoutes` property:

Defines route behavior based on the current locale. This method can be used to control access to specific routes based on available locales or to provide translations for specific locales.
---

## 🚦 `$defineI18nRoute(routeDefinition: { locales?: string[] | Record<string, Record<string, TranslationObject>>, localeRoutes?: Record<string, string> })`

Defines route behavior based on the current locale. This method can be used to control access to specific routes based on available locales, provide translations for specific locales, or set custom routes for different locales.

- **`locales`**: This property determines which locales are available for the route. It can be either:
- An **array of strings**, where each string represents an available locale (e.g., `['en', 'fr', 'de']`).
- An **object** where each key is a locale code, and the value is either an object containing translations or an empty object if you do not wish to provide translations for that locale.

- **`localeRoutes`**: This property allows you to define custom routes for specific locales. Each key represents a locale code, and the corresponding value is the custom route path for that locale. This is useful for handling scenarios where certain locales require different route structures or paths.

Example:

```typescript
$defineI18nRoute({
locales: {
en: { greeting: 'Hello', farewell: 'Goodbye' },
ru: { greeting: 'Привет', farewell: 'До свидания' },
de: { greeting: 'Hallo', farewell: 'Auf Wiedersehen' },
},
localeRoutes: {
ru: '/localesubpage', // Custom route path for the Russian locale
},
})
```

### Use Cases:

- **Controlling Access**: By specifying available locales, you can control which routes are accessible based on the current locale, ensuring that users only see content relevant to their language.

- **Providing Translations**: The `locales` object allows for providing specific translations for each route, enhancing the user experience by delivering content in the user's preferred language.

- **Custom Routing**: The `localeRoutes` property offers flexibility in defining different paths for specific locales, which can be particularly useful in cases where certain languages or regions require unique navigational flows or URLs.

- `locales`: This property determines which locales are available for the route. It can be either:
- An array of strings, where each string represents an available locale (e.g., `['en', 'fr', 'de']`).
- An object where each key is a locale code, and the value is either an object containing translations or an empty object if you do not wish to provide translations for that locale.
This function offers a flexible way to manage routing and localization in your Nuxt application, making it easy to tailor the user experience based on the language and region settings of your audience.

### Example 1: Controlling Access Based on Locales

Expand Down
82 changes: 82 additions & 0 deletions docs/guide/custom-locale-routes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
outline: deep
---

# 🔗 Custom Localized Routes with `localeRoutes` in `Nuxt I18n Micro`

## 📖 Introduction to `localeRoutes`

The `localeRoutes` feature in `Nuxt I18n Micro` allows you to define custom routes for specific locales, offering flexibility and control over the routing structure of your application. This feature is particularly useful when certain locales require different URL structures, tailored paths, or need to follow specific regional or linguistic conventions.

## 🚀 Primary Use Case of `localeRoutes`

The primary use case for `localeRoutes` is to provide distinct routes for different locales, enhancing the user experience by ensuring URLs are intuitive and relevant to the target audience. For example, you might have different paths for English and Russian versions of a page, where the Russian locale follows a localized URL format.

### 📄 Example: Defining `localeRoutes` in `$defineI18nRoute`

Here’s an example of how you might define custom routes for specific locales using `localeRoutes` in your `$defineI18nRoute` function:

```typescript
$defineI18nRoute({
localeRoutes: {
ru: '/localesubpage', // Custom route path for the Russian locale
de: '/lokaleseite', // Custom route path for the German locale
},
})
```

### 🔄 How `localeRoutes` Work

- **Default Behavior**: Without `localeRoutes`, all locales use a common route structure defined by the primary path.
- **Custom Behavior**: With `localeRoutes`, specific locales can have their own routes, overriding the default path with locale-specific routes defined in the configuration.

## 🌱 Use Cases for `localeRoutes`

### 📄 Example: Using `localeRoutes` in a Page

Here’s a simple Vue component demonstrating the use of `$defineI18nRoute` with `localeRoutes`:

```vue
<template>
<div>
<!-- Display greeting message based on the current locale -->
<p>{{ $t('greeting') }}</p>
<!-- Navigation links -->
<div>
<NuxtLink :to="$localeRoute({ name: 'index' })">
Go to Index
</NuxtLink>
|
<NuxtLink :to="$localeRoute({ name: 'about' })">
Go to About Page
</NuxtLink>
</div>
</div>
</template>
<script setup>
import { useNuxtApp } from '#imports'
const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $defineI18nRoute } = useNuxtApp()
// Define translations and custom routes for specific locales
$defineI18nRoute({
localeRoutes: {
ru: '/localesubpage', // Custom route path for Russian locale
},
})
</script>
```

### 🛠️ Using `localeRoutes` in Different Contexts

- **Landing Pages**: Use custom routes to localize URLs for landing pages, ensuring they align with marketing campaigns.
- **Documentation Sites**: Provide distinct routes for each locale to better match the localized content structure.
- **E-commerce Sites**: Tailor product or category URLs per locale for improved SEO and user experience.

## 📝 Best Practices for Using `localeRoutes`

- **🚀 Use for Relevant Locales**: Apply `localeRoutes` primarily where the URL structure significantly impacts the user experience or SEO. Avoid overuse for minor differences.
- **🔧 Maintain Consistency**: Keep a consistent routing pattern across locales unless there's a strong reason to deviate. This approach helps in maintaining clarity and reducing complexity.
- **📚 Document Custom Routes**: Clearly document any custom routes you define with `localeRoutes`, especially in modular applications, to ensure team members understand the routing logic.
49 changes: 38 additions & 11 deletions docs/guide/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,44 @@ routesLocaleLinks: {
}
```


### 🧩 `define`: `boolean`

Enables or disables the addition of a special `define` plugin that allows you to use Nuxt's runtime configuration for overriding settings in your translation files.

- **Default**: `true`
- **Example**:

```typescript
define: false // Disable the define plugin
```

## 🔄 `disablePageLocales`: `boolean`

The `disablePageLocales` option allows you to disable page-specific translations, limiting the module to only use global translation files. This can be particularly useful for projects where page-specific translations are not necessary or to simplify the translation management process by consolidating all translations into global files.

- **Default**: `false`

- **Example**:

```typescript
disablePageLocales: true // Disable page-specific translations, using only global translations
```

### 📂 Folder Structure with `disablePageLocales: true`

When `disablePageLocales` is enabled, the module will only use the translations defined in the global files located directly under the `locales` directory. Page-specific translation files (located in `/locales/pages`) will be ignored.

```
/locales
├── en.json
├── fr.json
└── ar.json
```

This setup is ideal for applications where the majority of the content is shared across pages or when consistency in translations is critical across the entire application. By disabling page-specific translations, you ensure that all translations are centralized, making it easier to maintain and update.


### 🔄 Caching Mechanism

One of the standout features of `Nuxt I18n Micro` is its **intelligent caching system**. When a translation is requested during server-side rendering (SSR), the result is stored in a cache. This means that subsequent requests for the same translation can retrieve the data from the cache rather than searching through the translation files again. This caching mechanism drastically reduces the time needed to fetch translations and significantly lowers the server's resource consumption.
Expand All @@ -197,17 +235,6 @@ However, it's important to note that **caching is only effective after the page

This caching strategy is particularly beneficial for high-traffic applications, where the same pages are frequently accessed by users. By minimizing the need to repeatedly load and process translation files, `Nuxt I18n Micro` ensures that your application remains responsive and efficient, even under heavy load.

### 🧩 `define`: `boolean`

Enables or disables the addition of a special `define` plugin that allows you to use Nuxt's runtime configuration for overriding settings in your translation files.

- **Default**: `true`
- **Example**:

```typescript
define: false // Disable the define plugin
```

## 🔄 Caching Mechanism

One of the standout features of `Nuxt I18n Micro` is its **intelligent caching system**. When a translation is requested during server-side rendering (SSR), the result is stored in a cache. This means that subsequent requests for the same translation can retrieve the data from the cache rather than searching through the translation files again. This caching mechanism drastically reduces the time needed to fetch translations and significantly lowers the server's resource consumption.
Expand Down
129 changes: 4 additions & 125 deletions docs/guide/performance-results.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ outline: deep

## Project Information

- **i18n-micro Path**: ./test/fixtures/i18n-micro
- **i18n Path**: ./test/fixtures/i18n
- **Test Script Location**: ./test/performance.test.ts
- **[i18n-micro Path](https://github.com/s00d/nuxt-i18n-micro/tree/main/test/fixtures/i18n-micro)**: ./test/fixtures/i18n-micro
- **[i18n Path](https://github.com/s00d/nuxt-i18n-micro/tree/main/test/fixtures/i18n)**: ./test/fixtures/i18n
- **[Test Script Location](https://github.com/s00d/nuxt-i18n-micro/tree/main/test/performance.test.ts)**: ./test/performance.test.ts


### Description:
This performance test compares two implementations of internationalization: **i18n-micro** and **i18n**.
Expand All @@ -20,125 +21,3 @@ This difference is attributed to its ability to handle more requests, which requ
It is essential to recognize that the example used in this test is not entirely representative of the intended usage pattern for **i18n-micro**. The example simplifies the translation structure by consolidating all translations into a single file. However, **i18n-micro** is optimized for scenarios where translations are organized on a per-page basis. This approach allows for more granular control and efficiency, particularly in large-scale applications. The current setup is used merely for demonstration purposes and may not fully showcase the potential performance benefits of **i18n-micro** in real-world applications.

---

## Build Performance for ./test/fixtures/i18n-micro

- **Build Time**: 7.76 seconds
- **Max CPU Usage**: 178.00%
- **Min CPU Usage**: 101.70%
- **Average CPU Usage**: 142.23%
- **Max Memory Usage**: 1176.38 MB
- **Min Memory Usage**: 194.41 MB
- **Average Memory Usage**: 670.34 MB


## Build Performance for ./test/fixtures/i18n

- **Build Time**: 96.57 seconds
- **Max CPU Usage**: 400.80%
- **Min CPU Usage**: 52.00%
- **Average CPU Usage**: 141.14%
- **Max Memory Usage**: 8511.80 MB
- **Min Memory Usage**: 198.84 MB
- **Average Memory Usage**: 3928.12 MB


### ⏱️ Build Time and Resource Consumption

::: details **i18n**
- **Build Time**: 96.57 seconds
- **Max CPU Usage**: 400.80%
- **Max Memory Usage**: 8511.80 MB
:::

::: details **i18n-micro**
- **Build Time**: 7.76 seconds
- **Max CPU Usage**: 178.00%
- **Max Memory Usage**: 1176.38 MB
:::

## Performance Comparison

- **i18n-micro**: 7.76 seconds, Max Memory: 1176.38 MB, Max CPU: 178.00%
- **i18n**: 96.57 seconds, Max Memory: 8511.80 MB, Max CPU: 400.80%
- **Time Difference**: -88.81 seconds
- **Memory Difference**: -7335.42 MB
- **CPU Usage Difference**: -222.80%

## Stress Test for ./test/fixtures/i18n-micro

- **Max CPU Usage During Stress Test**: 145.30%
- **Min CPU Usage During Stress Test**: 0.00%
- **Average CPU Usage During Stress Test**: 65.61%
- **Max Memory Usage During Stress Test**: 539.98 MB
- **Min Memory Usage During Stress Test**: 49.41 MB
- **Average Memory Usage During Stress Test**: 315.98 MB
- **Stress Test Time**: 113.72 seconds
- **Average Response Time**: 1662.08 ms
- **Min Response Time**: 174.79 ms
- **Max Response Time**: 3976.34 ms
- **Requests per Second**: 52.76
- **Error Rate**: 0.00%

## Stress Test for ./test/fixtures/i18n

- **Max CPU Usage During Stress Test**: 200.70%
- **Min CPU Usage During Stress Test**: 0.00%
- **Average CPU Usage During Stress Test**: 34.59%
- **Max Memory Usage During Stress Test**: 979.86 MB
- **Min Memory Usage During Stress Test**: 49.73 MB
- **Average Memory Usage During Stress Test**: 510.21 MB
- **Stress Test Time**: 200.05 seconds
- **Average Response Time**: 2264.46 ms
- **Min Response Time**: 68.52 ms
- **Max Response Time**: 26139.35 ms
- **Requests per Second**: 29.99
- **Error Rate**: 0.00%

## Stress Test Comparison

- **i18n-micro Stress Test**: Max Memory: 539.98 MB, Max CPU: 145.30%, Time: 113.72 seconds
- **i18n Stress Test**: Max Memory: 979.86 MB, Max CPU: 200.70%, Time: 200.05 seconds

- **Time Difference**: -86.32 seconds
- **Memory Difference**: -439.88 MB
- **CPU Usage Difference**: -55.40%
- **Response Time Difference**: -602.38 ms
- **Error Rate Difference**: 0.00%

### Total Requests Comparison

- **Total Successful Requests Difference**: 0
- **Total Failed Requests Difference**: 0

### Average Request Time Comparison

- **Average Request Time (i18n-micro)**: 1662.08 ms
- **Average Request Time (i18n)**: 2264.46 ms
- **Average Request Time Difference**: -602.38 ms

### Average Total Time Per 1000 Requests (for http://127.0.0.1:9999/page)

- **Average Time per 1000 Requests (i18n-micro) for http://127.0.0.1:9999/page**: 113.72 ms
- **Average Time per 1000 Requests (i18n) for http://127.0.0.1:9999/page**: 200.05 ms
- **Average Time per 1000 Requests Difference for http://127.0.0.1:9999/page**: -86.32 ms

## 📊 Detailed Performance Analysis

### 🔍 Test Logic Explanation

The performance tests conducted for `Nuxt I18n Micro` and `nuxt-i18n` are designed to simulate real-world usage scenarios. Below is an overview of the key aspects of the test methodology:

1. **Build Time**: Measures the time required to build the project, focusing on how efficiently each module handles large translation files.
2. **CPU Usage**: Tracks the CPU load during the build and stress tests to assess the impact on server resources.
3. **Memory Usage**: Monitors memory consumption to determine how each module manages memory, especially under high load.
4. **Stress Testing**: Simulates 10,000 requests to evaluate the server's ability to handle concurrent requests, measuring response times, error rates, and overall throughput.

### 🛠 Why This Approach?

The chosen testing methodology is designed to reflect the scenarios that developers are likely to encounter in production environments. By focusing on build time, CPU and memory usage, and server performance under load, the tests provide a comprehensive view of how each module will perform in a large-scale, high-traffic application.

**Nuxt I18n Micro** is optimized for:
- **Faster Build Times**: By reducing the overhead during the build process.
- **Lower Resource Consumption**: Minimizing CPU and memory usage, making it suitable for resource-constrained environments.
- **Better Handling of Large Projects**: With a focus on scalability, ensuring that applications remain responsive even as they grow.
Loading

0 comments on commit 59d1efe

Please sign in to comment.