Skip to content

Commit

Permalink
localization scope recipe (#317)
Browse files Browse the repository at this point in the history
* localization scope recipe

* .

* mv info section to routing file
  • Loading branch information
Paul-Bob authored Nov 21, 2024
1 parent dc4b1d6 commit a5b6991
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 37 deletions.
63 changes: 63 additions & 0 deletions docs/3.0/common/mount_avo_under_locale_scope_common.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Using a locale scope is an effective way to set the locale for your users.

### Only Avo engine

On the community plan, the only requirement is to wrap the Avo engine mount within the scope.

:::warning
This will work for Avo's engine routes but won't work for any of the nested engines.

If you're using `avo-pro`, `avo-advanced` or any other Avo engine check the next section.
:::

```ruby{4-6}
# config/routes.rb
Rails.application.routes.draw do
scope ":locale" do
mount Avo::Engine, at: Avo.configuration.root_path
end
end
```

### Avo engine and nested engines

Because of how Rails is mounting engines, that locale scope is not being applied to nested engines like `avo-advanced`, `avo-pro`, etc.

The fix here is to tell Avo not to mount the engines and have them mounted yourself.

```ruby {5}
# config/avo.rb

Avo.configure do |config|
# Disable automatic engine mounting
config.mount_avo_engines = false
end
```

Once automatic engine mounting is disabled, the next step is to mount the Avo engine and its nested engines within the locale scope.

```ruby {4-6,9-15}
# config/routes.rb

Rails.application.routes.draw do
scope ":locale" do
mount Avo::Engine, at: Avo.configuration.root_path
end
end

if defined? ::Avo
Avo::Engine.routes.draw do
scope "(:locale)" do # Take note of the parentheses
instance_exec(&Avo.mount_engines)
end
end
end
```

:::warning
Take note of the parentheses around the `(:locale)` scope when mounting the engines. These parentheses are essential to ensure proper functionality.
:::

This will instruct Rails to add the locale scope to all Avo nested engines too.

1 change: 1 addition & 0 deletions docs/3.0/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ config.logger = -> {
```

<Option name="`default_url_options`">

`default_url_options` is a Rails [controller method](https://apidock.com/rails/ActionController/Base/default_url_options) that will append params automatically to the paths you generate through path helpers.

In order to implement some features like route-level Multitenancy we exposed an API to add to Avo's `default_url_options` method.
Expand Down
63 changes: 63 additions & 0 deletions docs/3.0/guides/localization-scope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
outline: [2,3]
---

# Localization scope 🌍✨

Implementing a localization scope in Avo allows you to seamlessly adapt your application to support multiple languages, enhancing the user experience. This recipe will guide you through the steps to configure a locale scope, ensuring your application dynamically sets and respects the user's preferred language. Let's dive in!

## 1. Mount Avo within a `:locale` scope

<!-- @include: ./../common/mount_avo_under_locale_scope_common.md-->

## 2. Setup `default_url_options`

To ensure that the `:locale` scope is consistently included in generated URLs, it must be explicitly added to Avo's `default_url_options` configuration. This step is vital for preserving the user's language preferences throughout the application. Without this configuration, the locale parameter might be omitted, leading to unexpected language switches or inconsistent localization behavior.

Here's how you can set it up:

```ruby{4}
# config/avo.rb
Avo.configure do |config|
# Add :locale to default URL options
config.default_url_options = [:locale]
end
```

This configuration guarantees that every URL generated by Avo includes the `:locale` parameter, aligning navigation with the user's language preferences.

## 3. Apply the `locale` Scope

To properly handle localization within Avo, you'll need to ensure the `locale` parameter is respected throughout the request.

:::info
If you've already ejected the `Avo::ApplicationController`, you can skip the ejection step below.
:::

### Eject the `Avo::ApplicationController`

Run the following command to eject the `Avo::ApplicationController`:

```bash
rails generate avo:eject --controller application_controller
```

This command generates a customizable version of the `Avo::ApplicationController`, allowing you to override default behaviors.

### Override the `set_avo_locale` method

Next, override the `set_avo_locale` method to ensure that the `locale` parameter is applied throughout the request lifecycle. Update your controller as follows:

```ruby{5-7}
# app/controllers/avo/application_controller.rb
module Avo
class ApplicationController < BaseApplicationController
def set_avo_locale(&action)
I18n.with_locale(params[:locale], &action)
end
end
end
```

This implementation uses `I18n.with_locale` to set the desired locale for the duration of the request, ensuring consistent localization behavior across Avo's interface.
5 changes: 5 additions & 0 deletions docs/3.0/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,8 @@ pt-BR:
one: 'usuário'
other: 'usuários'
```

### Using a Route Scope for Localization

To implement a route scope for localization within Avo, refer to [this guide](guides/localization-scope). It provides step-by-step instructions on configuring your routes to include a locale scope, enabling seamless localization handling across your application.

47 changes: 10 additions & 37 deletions docs/3.0/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,47 +40,20 @@ end

Sometimes you might have more exotic use-cases so you'd like to customize those paths accordingly.

## Mount Avo under a `:locale` scope
## Mount Avo under a scope

Having a locale scope is a good way to set the locale for your users. Because of how Rails is mounting engines, that locale scope is not being applied to nested engines, so you'll need to nest them yourself.
:::info
The `:locale` scope provided is just an example. If your objective is to implement a route scope for localization within Avo, there's a detailed recipe available (including this step). Check out [this guide](guides/localization-scope) for comprehensive instructions.

```ruby
# This will work for Avo's routes but won't work for the nested engines.
Rails.application.routes.draw do
scope ":locale" do
mount Avo::Engine, at: Avo.configuration.root_path
end
end
```

The fix here is to tell Avo not to mount the engines and have them mounted yourself.

::: code-group
```ruby [config/avo.rb]{3}
Avo.configure do |config|
# Disable automatic engine mounting
config.mount_avo_engines = false
If your goal is adding another scope unrelated to localization, you're in the right place. This approach works for other types of scoped routing as well.
:::

# other configuration
end
```
In this example, we'll demonstrate how to add a `:locale` scope to your routes.

```ruby [config/routes.rb]{2-4,10-14}
Rails.application.routes.draw do
scope ":locale" do
mount Avo::Engine, at: Avo.configuration.root_path
end
<!-- @include: ./common/mount_avo_under_locale_scope_common.md-->

# other routes
end
:::info
To guarantee that the `locale` scope is included in the `default_url_options`, you must explicitly add it to the Avo configuration.

if defined? ::Avo
Avo::Engine.routes.draw do
scope ":locale" do
instance_exec(&Avo.mount_engines)
end
end
end
```
Check [this documentation section](customization.html#default_url_options) for details on how to configure `default_url_options` setting.
:::
This will instruct Rails to add the locale scope to all Avo nested engines too.

0 comments on commit a5b6991

Please sign in to comment.