Class LocalizedField<F extends com.vaadin.flow.component.textfield.TextFieldBase<F,String>>

java.lang.Object
com.vaadin.flow.component.Component
com.vaadin.flow.component.AbstractField<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,Map<Locale,String>>
com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>
org.vaadin.firitin.components.customfield.VCustomField<Map<Locale,String>>
org.vaadin.firitin.fields.localized.LocalizedField<F>
Type Parameters:
F - the type of text editor used for each language
All Implemented Interfaces:
com.vaadin.flow.component.AttachNotifier, com.vaadin.flow.component.BlurNotifier<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>>, com.vaadin.flow.component.DetachNotifier, com.vaadin.flow.component.Focusable<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>>, com.vaadin.flow.component.FocusNotifier<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>>, com.vaadin.flow.component.HasElement, com.vaadin.flow.component.HasEnabled, com.vaadin.flow.component.HasHelper, com.vaadin.flow.component.HasLabel, com.vaadin.flow.component.HasSize, com.vaadin.flow.component.HasStyle, com.vaadin.flow.component.HasTheme, com.vaadin.flow.component.HasValidation, com.vaadin.flow.component.HasValue<com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,Map<Locale,String>>,Map<Locale,String>>, com.vaadin.flow.component.HasValueAndElement<com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,Map<Locale,String>>,Map<Locale,String>>, com.vaadin.flow.component.shared.HasTooltip, com.vaadin.flow.component.shared.HasValidationProperties, com.vaadin.flow.component.shared.InputField<com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,Map<Locale,String>>,Map<Locale,String>>, Serializable, FluentAttachNotifier<VCustomField<Map<Locale,String>>>, FluentBlurNotifier<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,VCustomField<Map<Locale,String>>>, FluentComponent<VCustomField<Map<Locale,String>>>, FluentDetachNotifier<VCustomField<Map<Locale,String>>>, FluentFocusable<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,VCustomField<Map<Locale,String>>>, FluentFocusNotifier<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,VCustomField<Map<Locale,String>>>, FluentHasEnabled<VCustomField<Map<Locale,String>>>, FluentHasHelper<VCustomField<Map<Locale,String>>>, FluentHasSize<VCustomField<Map<Locale,String>>>, FluentHasTooltip<VCustomField<Map<Locale,String>>>, FluentHasValidation<VCustomField<Map<Locale,String>>>, FluentHasValueAndElement<VCustomField<Map<Locale,String>>,com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>,Map<Locale,String>>,Map<Locale,String>>, FluentHasLabel<VCustomField<Map<Locale,String>>>
Direct Known Subclasses:
LocalizedTextArea, LocalizedTextField

@StyleSheet("context://assets/org/vaadin/firitin/components/localized-field.css") public abstract class LocalizedField<F extends com.vaadin.flow.component.textfield.TextFieldBase<F,String>> extends VCustomField<Map<Locale,String>>
Base class for a CustomField that edits the language versions of a single piece of text. The field value is a map from locale to the entered text, and the user edits one language at a time in a single text editor (a TextField or TextArea).

The language to edit is picked with a selector at the top of a bordered box: a Tabs tab bar by default, or a ComboBox once there are more languages than getDefaultComboBoxThreshold() (configurable), since a tab bar becomes unwieldy with very many languages. Languages are always shown in alphabetical order of their localized name.

The localized-field class on this component activates the styling in localized-field.css (loaded via the StyleSheet annotation below): a plain bordered box with the selector as a shaded header above a straight divider, the editor filling the box with no chrome of its own, and (in tab mode) the active language marked with an underline. The styling is theme-agnostic and works in both the Aura and Lumo themes; the two selector modes look the same in spirit.

A Translator can fill the other languages from the currently edited one via a small "magic" action in the corner. It is discovered automatically from the Instantiator (so registering a Spring bean is enough for the action to appear), or set explicitly with setTranslator(Translator).

See Also:
  • Nested Class Summary

    Nested classes/interfaces inherited from class com.vaadin.flow.component.AbstractField

    com.vaadin.flow.component.AbstractField.ComponentValueChangeEvent<C extends com.vaadin.flow.component.Component,V>

    Nested classes/interfaces inherited from interface com.vaadin.flow.component.BlurNotifier

    com.vaadin.flow.component.BlurNotifier.BlurEvent<C extends com.vaadin.flow.component.Component>

    Nested classes/interfaces inherited from interface com.vaadin.flow.component.FocusNotifier

    com.vaadin.flow.component.FocusNotifier.FocusEvent<C extends com.vaadin.flow.component.Component>

    Nested classes/interfaces inherited from interface com.vaadin.flow.component.HasValue

    com.vaadin.flow.component.HasValue.ValueChangeEvent<V>, com.vaadin.flow.component.HasValue.ValueChangeListener<E extends com.vaadin.flow.component.HasValue.ValueChangeEvent<?>>
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
     
    protected
    LocalizedField(List<Locale> locales, int comboBoxThreshold)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    protected abstract F
    Creates the editor used to edit a single language.
    protected String
    flagFor(Locale locale)
    Returns a flag emoji visualizing the language of the given locale, or an empty string if none is known.
    protected Map<Locale,String>
     
    static int
    The default number of languages above which new instances use a ComboBox instead of a Tabs bar to select the language.
    The language whose editor is currently shown.
    Returns the ActionButton that triggers the "translate to other languages" action, so its presentation can be customized: get its inner button via ActionButton.getButton() to change the icon, text, theme variants or tooltip, set a busy text, show its progress bar, etc.
    The effective translator: the explicitly set one if setTranslator(org.vaadin.firitin.fields.localized.Translator) has been called, otherwise the one discovered from the Instantiator (or null if none).
    com.vaadin.flow.data.converter.Converter<Map<Locale,String>,Map<String,String>>
    A Binder converter between this field's value (Map<Locale, String>) and a Map<String, String> keyed by language code (e.g.
    protected String
    The capitalized, localized language name, used both as the selector label and as the accessible name of the language's editor.
    protected void
    onAttach(com.vaadin.flow.component.AttachEvent attachEvent)
     
    static void
     
    void
    Sets the field label and propagates it to each language editor's accessible name (as "Label (Language)"), so screen readers and label-based test selectors (e.g.
    protected void
     
    void
    Selects the language whose editor is shown (the "open" one).
    void
    Sets the Translator used by the "translate to other languages" action.
    protected String
    tabLabel(Locale locale)
    The text shown for a locale in the selector: the flag (if any) from flagFor(Locale) followed by the languageName(Locale).
    protected String
    The label of the translate action.

    Methods inherited from class org.vaadin.firitin.components.customfield.VCustomField

    withErrorMessage, withInvalid

    Methods inherited from class com.vaadin.flow.component.customfield.CustomField

    add, addThemeVariants, getLabel, remove, removeThemeVariants, updateValue

    Methods inherited from class com.vaadin.flow.component.AbstractField

    addValueChangeListener, bindValue, getEmptyValue, getValue, isEmpty, setModelValue, setValue, valueEquals

    Methods inherited from class com.vaadin.flow.component.Component

    addListener, bindVisible, findAncestor, fireEvent, from, get, getChildren, getElement, getEventBus, getId, getListeners, getLocale, getParent, getTestId, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getTranslation, getUI, hasListener, isAttached, isTemplateMapped, isVisible, onDetach, onEnabledStateChanged, removeFromParent, scrollIntoView, scrollIntoView, set, setElement, setId, setTestId, setVisible

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface com.vaadin.flow.component.AttachNotifier

    addAttachListener

    Methods inherited from interface com.vaadin.flow.component.BlurNotifier

    addBlurListener

    Methods inherited from interface com.vaadin.flow.component.DetachNotifier

    addDetachListener

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentAttachNotifier

    withAttachListener

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentBlurNotifier

    withBlurListener

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentComponent

    navigate, setId, setVisible, withId, withVisible

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentDetachNotifier

    withDetachListener

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentFocusable

    withTabIndex

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentFocusNotifier

    withFocusListener

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentHasEnabled

    withEnabled

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentHasHelper

    withHelperComponent, withHelperText

    Methods inherited from interface org.vaadin.firitin.fluency.ui.internal.FluentHasLabel

    withLabel

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentHasTooltip

    withTooltip

    Methods inherited from interface org.vaadin.firitin.fluency.ui.FluentHasValueAndElement

    withReadOnly, withRequiredIndicatorVisible, withValue, withValueChangeListener

    Methods inherited from interface com.vaadin.flow.component.Focusable

    addFocusShortcut, blur, focus, focus, getTabIndex, setTabIndex

    Methods inherited from interface com.vaadin.flow.component.FocusNotifier

    addFocusListener

    Methods inherited from interface com.vaadin.flow.component.HasElement

    getElement

    Methods inherited from interface com.vaadin.flow.component.HasEnabled

    bindEnabled, isEnabled, setEnabled

    Methods inherited from interface com.vaadin.flow.component.HasHelper

    bindHelperText, getHelperComponent, getHelperText, setHelperComponent, setHelperText

    Methods inherited from interface com.vaadin.flow.component.HasLabel

    getLabel

    Methods inherited from interface com.vaadin.flow.component.HasSize

    bindHeight, bindWidth, getHeight, getHeightUnit, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getWidth, getWidthUnit, setHeight, setHeight, setHeightFull, setMaxHeight, setMaxHeight, setMaxWidth, setMaxWidth, setMinHeight, setMinHeight, setMinWidth, setMinWidth, setSizeFull, setSizeUndefined, setWidth, setWidth, setWidthFull

    Methods inherited from interface com.vaadin.flow.component.HasStyle

    addClassName, addClassNames, bindClassName, bindClassNames, getClassName, getClassNames, getStyle, hasClassName, removeClassName, removeClassNames, setClassName, setClassName

    Methods inherited from interface com.vaadin.flow.component.HasTheme

    addThemeName, addThemeNames, bindThemeName, bindThemeNames, getThemeName, getThemeNames, hasThemeName, removeThemeName, removeThemeNames, setThemeName, setThemeName

    Methods inherited from interface com.vaadin.flow.component.shared.HasTooltip

    getTooltip, setTooltipMarkdown, setTooltipText

    Methods inherited from interface com.vaadin.flow.component.HasValidation

    setManualValidation

    Methods inherited from interface com.vaadin.flow.component.shared.HasValidationProperties

    getErrorMessage, isInvalid, setErrorMessage, setInvalid

    Methods inherited from interface com.vaadin.flow.component.HasValue

    addValueChangeListener, bindValue, clear, getEmptyValue, getOptionalValue, getValue, isEmpty, setValue

    Methods inherited from interface com.vaadin.flow.component.HasValueAndElement

    bindReadOnly, bindRequiredIndicatorVisible, isReadOnly, isRequiredIndicatorVisible, setReadOnly, setRequiredIndicatorVisible
  • Constructor Details

    • LocalizedField

      protected LocalizedField(List<Locale> locales)
    • LocalizedField

      protected LocalizedField(List<Locale> locales, int comboBoxThreshold)
  • Method Details

    • setLabel

      public void setLabel(String label)
      Sets the field label and propagates it to each language editor's accessible name (as "Label (Language)"), so screen readers and label-based test selectors (e.g. getByLabel) can reach the inner editor even though the visible label sits on the wrapping custom field.
      Specified by:
      setLabel in interface com.vaadin.flow.component.HasLabel
      Overrides:
      setLabel in class com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>
    • onAttach

      protected void onAttach(com.vaadin.flow.component.AttachEvent attachEvent)
      Overrides:
      onAttach in class com.vaadin.flow.component.Component
    • setSelectedLocale

      public void setSelectedLocale(Locale locale)
      Selects the language whose editor is shown (the "open" one). By default this is the user's own language if editable, otherwise the alphabetically first; calling this overrides that default.
      Throws:
      IllegalArgumentException - if the locale is not one of the field's editable languages
    • getSelectedLocale

      public Locale getSelectedLocale()
      The language whose editor is currently shown.
    • getDefaultComboBoxThreshold

      public static int getDefaultComboBoxThreshold()
      The default number of languages above which new instances use a ComboBox instead of a Tabs bar to select the language.
    • setDefaultComboBoxThreshold

      public static void setDefaultComboBoxThreshold(int threshold)
    • setTranslator

      public void setTranslator(Translator translator)
      Sets the Translator used by the "translate to other languages" action. When set to a non-null value the action becomes visible; when set to null it is hidden.

      Calling this explicitly overrides any translator the component would otherwise discover from the Instantiator on attach (e.g. a registered Spring bean). In particular, calling it with null turns the action off even when such a translator exists.

    • getTranslator

      public Translator getTranslator()
      The effective translator: the explicitly set one if setTranslator(org.vaadin.firitin.fields.localized.Translator) has been called, otherwise the one discovered from the Instantiator (or null if none).
    • getTranslateButton

      public ActionButton<Map<Locale,String>> getTranslateButton()
      Returns the ActionButton that triggers the "translate to other languages" action, so its presentation can be customized: get its inner button via ActionButton.getButton() to change the icon, text, theme variants or tooltip, set a busy text, show its progress bar, etc. The component manages the button's visibility (tied to the available Translator) and its action, so avoid overriding those.
    • translateButtonText

      protected String translateButtonText()
      The label of the translate action. Override to localize it.
    • createField

      protected abstract F createField(Locale locale)
      Creates the editor used to edit a single language. The aria label, value change mode, change listener and width are configured by the base class.
    • tabLabel

      protected String tabLabel(Locale locale)
      The text shown for a locale in the selector: the flag (if any) from flagFor(Locale) followed by the languageName(Locale). Override to fully customize the label.
    • languageName

      protected String languageName(Locale locale)
      The capitalized, localized language name, used both as the selector label and as the accessible name of the language's editor.
    • flagFor

      protected String flagFor(Locale locale)
      Returns a flag emoji visualizing the language of the given locale, or an empty string if none is known. The country is taken from the locale itself when present, otherwise derived from the language for the most common languages. Override to support more languages or to pick a different country for a language (e.g. US instead of GB for English).
    • generateModelValue

      protected Map<Locale,String> generateModelValue()
      Specified by:
      generateModelValue in class com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>
    • setPresentationValue

      protected void setPresentationValue(Map<Locale,String> value)
      Specified by:
      setPresentationValue in class com.vaadin.flow.component.customfield.CustomField<Map<Locale,String>>
    • languageCodeMapConverter

      public com.vaadin.flow.data.converter.Converter<Map<Locale,String>,Map<String,String>> languageCodeMapConverter()
      A Binder converter between this field's value (Map<Locale, String>) and a Map<String, String> keyed by language code (e.g. "fi"), for domain models that store translations by code — a common shape, e.g. a jsonb column.

      Conversion is by language code only (country variants are ignored), and the presentation side is rebuilt with this field's own locales, so the round trip is stable regardless of how the codes relate to the field's locales. Bind with:

       binder.forField(field)
             .withConverter(field.languageCodeMapConverter())
             .bind(MyBean::getTexts, MyBean::setTexts); // Map<String,String>
       
      For a wrapper type (such as a TranslatedText backed by a Map<String, String>), chain a further converter or bind through its map accessor.
      Returns:
      a converter from the field value to a language-code-keyed map