Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/components/AssemblyLine/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ given in the first part of the tuple.

<a id="AssemblyLine.language.get_language_list"></a>

#### get\_language\_list(languages: Optional[List[Tuple[str, str]]] = None, current="", lang\_codes: Optional[List[str]] = None, languages\_path: Optional[str] = None, event\_name="al\_change\_language")
#### get\_language\_list(languages: Optional[List[Tuple[str, str]]] = None, current="", lang\_codes: Optional[List[str]] = None, languages\_path: Optional[str] = None, event\_name="al\_get\_language\_list\_change\_language")

```python
def get_language_list(languages: Optional[List[Tuple[str, str]]] = None,
current="",
lang_codes: Optional[List[str]] = None,
languages_path: Optional[str] = None,
event_name="al_change_language") -> str
event_name="al_get_language_list_change_language") -> str
```

Given a list of language codes, returns
Expand Down Expand Up @@ -157,4 +157,3 @@ given in the first part of the tuple.
**Returns**:

- `str` - A string containing the HTML for an unordered inline list item for language selection.

31 changes: 23 additions & 8 deletions docs/components/AssemblyLine/magic_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,18 +459,33 @@ code: |

#### `al_user_language`

The currently selected language for the user. This is typically set automatically
through the language selection interface or URL parameters, but can be set directly
if needed.
The interview-wide language choice. This is typically set automatically through
URL parameters, an early language question, or the inline language list, but can
be set directly if needed.

If `session_local.al_user_language` is set, Assembly Line will use that
browser-session value first and only fall back to `al_user_language` when no
session-local override exists.

#### `al_change_language` (event)

An event triggered when the user clicks a language selection link. The event
handler automatically updates `al_user_language` based on the `lang` action
argument and calls Docassemble's `set_language()` function.
An event triggered when the user clicks a language selection link from the
navigation dropdown. The event handler stores the selected language in
`session_local.al_user_language` and calls Docassemble's `set_language()`
function.

This event is used internally by `get_language_list_dropdown()` so one browser
session can switch languages without changing the interview-wide language for
other users.

#### `al_get_language_list_change_language` (event)

An event triggered by the inline `get_language_list()` helper. The event handler
updates `al_user_language` from the `lang` action argument and calls
Docassemble's `set_language()` function.

This event is used internally by the language switching functions like
`get_language_list_dropdown()` and `get_language_list()`.
Use this behavior when you want the language choice to become the shared,
interview-wide default for the current run of the interview.

### Screen reader control

Expand Down
80 changes: 55 additions & 25 deletions docs/components/AssemblyLine/translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,17 @@ all Assembly Line special variables, see [Special variables](magic_variables.md)
* `enable_al_language`: defaults to True, turning it off can partially ensure the language system in AssemblyLine doesn't interfere with existing language systems. It should be relatively easy for authors to migrate to this new system though.
* `al_user_default_language`: can be controlled by interview author, this determines the language when the user makes no selection of their own. Defaults to "en".
* `al_interview_languages`: a list of language codes, presumably ISO-639-1 (Alpha-2), like ["en","es"] etc. The Assembly Line also contains a translation of several common language codes into the native-language version of the language (e.g., `es` is translated as `Español`).
* `al_user_language`: normally set via a dropdown menu or passed as a URL argument, this stores the user's current selected language
* `al_user_language`: normally set via a URL argument, a language question, or the inline language list. This stores the interview-wide language choice.
* `session_local.al_user_language`: an optional browser-session override used by the navigation dropdown. If it is set, the interview will use this value before falling back to `al_user_language`.

## Session-local and interview-wide language choices

Assembly Line now supports two layers of language selection:

1. `al_user_language` is the interview-wide language. Use it when you want the primary user's language choice to remain the default for the interview, such as from a landing page, an early language question, or the inline `get_language_list()` helper.
1. `session_local.al_user_language` is a per-session override. The navigation dropdown uses it so one browser session can switch languages without changing the language another user sees in the same interview.

This is especially useful in multi-user interviews. For example, one signer can keep the interview in Spanish while an advocate or a second signer views the same interview in English.

## Make the translation file available in your interview

Expand Down Expand Up @@ -119,14 +129,18 @@ When `al_interview_languages` is defined (which is the default) and has at least
the Assembly Line will add a drop-down menu item in the top right that allows the user
to switch languages at any time.

The drop-down menu now changes language only for the current browser session by setting
`session_local.al_user_language`. This makes it a good fit for live help, advocate review,
and multi-user interviews where different people may need different languages at the same time.

You can customize this drop-down menu with a block like this:

```yaml
---
default screen parts:
navigation bar html: |
% if enable_al_language and len(al_interview_languages) > 1:
${ get_language_list_dropdown(al_interview_languages,current=al_user_language, extra_class="text-dark", icon="fa-solid fa-language fa-xl" ) }
${ get_language_list_dropdown(al_interview_languages, current=session_local.attr("al_user_language") or al_user_language, extra_class="text-dark", icon="fa-solid fa-language fa-xl") }
% endif
```

Expand All @@ -145,6 +159,9 @@ rather than directing them to the dropdown menu.

You can call `get_language_list()` to achieve this.

This helper uses the `al_get_language_list_change_language` event by default, so it updates
the interview-wide `al_user_language` instead of the session-local override.

Example:

```yaml
Expand All @@ -155,7 +172,8 @@ subquestion: |
### Ask the user a question

If you want to be absolutely sure that the user encounters the language
question, you can directly ask the user a question:
question, you can directly ask the user a question. Setting `al_user_language`
this way updates the interview-wide language choice:

```yaml
id: language
Expand Down Expand Up @@ -195,42 +213,54 @@ E.g.,
`https://apps.suffolklitlab.org/start/uptocode/?lang=es`

The interview will launch in the language specified by
the language code (if it is translated into that language)
the language code (if it is translated into that language).

This sets the interview-wide `al_user_language`, so it is still the best choice
for language-specific landing pages and other entry points where you want the
language choice to be sticky.

:::note
If the URL already has a `?` in it, replace the `?` with an `&`.

(this is a standard part of URL arguments).
:::

## The `al_change_language` event
## The `al_change_language` and `al_get_language_list_change_language` events

The Assembly Line language system uses a special event called `al_change_language`
to handle language switching. This event is triggered automatically when a user
clicks on a language selection link generated by functions like
`get_language_list_dropdown()` or `get_language_list()`.
Assembly Line now uses two language-switching events:

When the event is triggered, it:
1. `al_change_language` is used by `get_language_list_dropdown()`. It stores the selected language in `session_local.al_user_language`, so the change only affects the current browser session.
1. `al_get_language_list_change_language` is used by `get_language_list()`. It updates `al_user_language`, so the change becomes the interview-wide language choice.

1. Reads the `lang` parameter from the action arguments
2. Sets `al_user_language` to the selected language code
3. Calls Docassemble's `set_language()` function to apply the language change
On each request, the built-in `initial: True` block checks for `session_local.attr("al_user_language")`
first. If that value exists, Assembly Line applies it. Otherwise it falls back to `al_user_language`.

You normally don't need to handle this event directly, as it's managed automatically
by the language switching functions. However, if you want to add custom behavior
when languages are switched, you can define additional logic after the language
change:
You normally do not need to define either event yourself, but this is the current built-in logic:

```yaml
---
initial: True
code: |
if enable_al_language:
if session_local.attr("al_user_language"):
set_language(session_local.attr("al_user_language"))
else:
set_language(al_user_language)
process_action()
---
event: al_change_language
code: |
# The built-in language switching happens first
if 'lang' in action_arguments():
al_user_language = action_argument('lang')
# Set browser-specific language for this interview session
if "lang" in action_arguments():
session_local.al_user_language = action_argument("lang")
set_language(session_local.al_user_language)
---
event: al_get_language_list_change_language
code: |
# Set the interview-wide language
if "lang" in action_arguments():
al_user_language = action_argument("lang")
set_language(al_user_language)

# Add your custom logic here
log(f"User switched to language: {al_user_language}")
```

## A complete example
Expand All @@ -253,7 +283,7 @@ default screen parts:
# Customizing this section isn't required. Here
navigation bar html: |
% if enable_al_language and len(al_interview_languages) > 1:
${ get_language_list_dropdown(al_interview_languages,current=al_user_language, extra_class="text-dark", icon="fa-solid fa-language fa-xl" ) }
${ get_language_list_dropdown(al_interview_languages, current=session_local.attr("al_user_language") or al_user_language, extra_class="text-dark", icon="fa-solid fa-language fa-xl") }
% endif
---
sections:
Expand Down Expand Up @@ -316,4 +346,4 @@ Also, see the documentation for the [AL language module](language.md) for comple

* [MADE](https://gbls.org/MADE), ([GitHub source code](https://github.com/GBLS/docassemble-maevictiondefense))
* [UpToCode](https://getuptocode.org), ([GitHub source code][https://github.com/LemmaLegalConsulting/docassemble-HousingCodeChecklist])
* [Massachusetts 209A Abuse Prevention Petition](https://courtformsonline.org/dv/#209A), ([GitHub source code](https://github.com/suffolklitlab/docassemble-MA209AProtectiveOrder))
* [Massachusetts 209A Abuse Prevention Petition](https://courtformsonline.org/dv/#209A), ([GitHub source code](https://github.com/suffolklitlab/docassemble-MA209AProtectiveOrder))
Loading