diff --git a/docs/components/AssemblyLine/language.md b/docs/components/AssemblyLine/language.md index e08beac65..72d1826e4 100644 --- a/docs/components/AssemblyLine/language.md +++ b/docs/components/AssemblyLine/language.md @@ -105,14 +105,14 @@ given in the first part of the tuple. -#### 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 @@ -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. - diff --git a/docs/components/AssemblyLine/magic_variables.md b/docs/components/AssemblyLine/magic_variables.md index 1cd49b3a3..4feca1de6 100644 --- a/docs/components/AssemblyLine/magic_variables.md +++ b/docs/components/AssemblyLine/magic_variables.md @@ -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 diff --git a/docs/components/AssemblyLine/translation.md b/docs/components/AssemblyLine/translation.md index 97f2b80e1..b72bde183 100644 --- a/docs/components/AssemblyLine/translation.md +++ b/docs/components/AssemblyLine/translation.md @@ -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 @@ -119,6 +129,10 @@ 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 @@ -126,7 +140,7 @@ You can customize this drop-down menu with a block like this: 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 ``` @@ -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 @@ -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 @@ -195,7 +213,11 @@ 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 `&`. @@ -203,34 +225,42 @@ 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 @@ -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: @@ -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)) \ No newline at end of file +* [Massachusetts 209A Abuse Prevention Petition](https://courtformsonline.org/dv/#209A), ([GitHub source code](https://github.com/suffolklitlab/docassemble-MA209AProtectiveOrder))