A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://plugins.jetbrains.com/docs/intellij/internationalization.html below:

Internationalization | IntelliJ Platform Plugin SDK

Internationalization

To enable IntelliJ-based IDEs and plugins for National Language Support (NLS), all String instances in the code can be split into three categories:

By default, a string is considered as non-NLS.

NLS Annotations

There is a set of NLS-related annotations, which can be used for annotating strings in the IDE or plugin code. Annotating strings enables inspecting NLS string content correctness.

For example, if an API method parameter is annotated as an NLS string, any hardcoded string passed as a value will be reported and extracting it to a message bundle will be proposed as a quick fix. Another example is inspecting whether a given string value is properly capitalized for the usage context.

Internationalization-related inspections can be enabled in in the following groups (some inspections require enabling Java Internationalization bundled plugin):

Consider using the following annotations:

NLS Context Annotations

NLS context annotations are semantic annotations describing the context where the annotated strings are intended to be used. For example, @InspectionMessage should be used for strings displayed as messages reported by inspections.

NLS context annotations must be annotated with @Nls and they can define:

The IntelliJ Platform provides NLS context annotations, including:

To find all available annotations, search for @NlsContext usages in the intellij-community source code.

If the provided set of NLS context annotations are not sufficient, create custom annotations.

A Single NLS Category Restriction

It is important not to use the same string instance for both NLS and non-NLS categories. If it is required to use some class as a key in configuration files and present it in the UI, create two separate methods (getId, getDisplayName) even if they return the same value in the default locale.

Avoiding Non-NLS Strings in Message Bundle

To enable localization, all NLS strings must be placed in resource bundle files. It is important to avoid adding non-NLS strings to a resource bundle. At best, this will add unnecessary work for translators, but it is also quite possible that if such a string is translated, it could break some features.

Message Bundles

All NLS strings from a module should be added to a *.properties file. A standard location of message files in JAR is /messages/*.properties. In Gradle-based plugin project sources, message files are located in $MODULE_ROOT$/src/main/resources/messages/*.properties.

A standard convention for naming a message bundle properties file is *Bundle.properties.

If a plugin project is multi-module, and it combines resources into a single JAR, make sure that all bundle files have unique names or paths. Otherwise, only the last packed bundle file will exist in the distribution package.

A corresponding bundle class should be used to access the strings from the code.

Enable Plugin DevKit | Plugin descriptor | Plugin.xml i18n verification inspection for reporting hardcoded texts in plugin descriptor files.

Message Bundle Class

The recommended approach to create a bundle class is to delegate getting messages to DynamicBundle, e.g.:

@NonNls private const val BUNDLE = "messages.ExampleBundle" internal object ExampleBundle { private val INSTANCE = DynamicBundle(ExampleBundle::class.java, BUNDLE) fun message( key: @PropertyKey(resourceBundle = BUNDLE) String, vararg params: Any ): @Nls String { return INSTANCE.getMessage(key, *params) } fun lazyMessage( @PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any ): Supplier<@Nls String> { return INSTANCE.getLazyMessage(key, *params) } }

final class ExampleBundle { @NonNls private static final String BUNDLE = "messages.ExampleBundle"; private static final DynamicBundle INSTANCE = new DynamicBundle(ExampleBundle.class, BUNDLE); private ExampleBundle() {} public static @NotNull @Nls String message( @NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params ) { return INSTANCE.getMessage(key, params); } public static Supplier<@Nls String> lazyMessage( @NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params ) { return INSTANCE.getLazyMessage(key, params); } }

Do not extend DynamicBundle in bundle classes.

Annotating message key parameter with @PropertyKey adds the IDE support in the client code, e.g., reporting unresolved message keys.

Moving Strings to Message Bundles

Make sure the encoding for bundle files is set to UTF-8 in .

IntelliJ IDEA provides inspections with fixes which help with moving strings to message bundles, e.g. for Java and Kotlin code.

It is possible to move multiple hardcoded strings to a message bundle in batch mode.

Moving Hardcoded Strings to a Message Bundle
  1. Invoke the action.

  2. Select the Hardcoded strings inspection.

  3. Select the inspection scope and run the inspection.

  4. In the Problems tool window, select the items to internationalize.

  5. Invoke the I18nize hardcoded string literal quick fix.

  6. Provide the message bundle file and resource bundle expression.

  7. Review the internationalized messages. It is possible to delete items and adjust their keys.

  8. Click the OK button.

    Internationalization Tips Property Keys

    It is important to specify a prefix for the property key describing the context in which UI string is used, especially for short strings.

    For example, set=Set property is hard to translate as the message usage context is unclear. It is required to find usages of such a message to properly translate it, which is a very time-consuming process. Also, other developers may reuse the same property for a different meaning of the word, and after that it will be impossible to translate it correctly.

    The simplest way to specify the prefix is annotating the parameter with one of @NlsContext annotations. It will cause the IDE to generate prefix and suffix automatically when the string is moved to a message bundle.

    Using & in Messages

    The & symbol in message bundles is used to specify mnemonic characters for buttons and labels. To use & in a value, escape it by a backslash (note that you also need to escape the backslash symbol):

    section.title=Drag \\& Drop

    Long Values

    To wrap a long value in a message bundle, put a backslash at the end of the line, and continue the value on the next line with an indent. Starting spaces on the next line are ignored, so if a space character is required before the word in the next line, add a space before the backslash:

    key=very, very long \ description

    In the above example, message("key") evaluates to very, very long description.

    Note that the backslash at the end of a line doesn't add a line break into the resulting value. For line breaks, use \n.

    Avoid Programmatic String Transformations

    They include but are not limited to:

    Such transformations make the incorrect assumption about:

    In all above cases, it is better to put the result string into the bundle. Example:

    Wrong

    Correct

    Message bundle:

    term.node=node ‎

    Code:

    message("term.node") pluralize(message("term.node"))

    Message bundle:

    term.node=node term.nodes=nodes

    Code:

    message("term.node") message("term.nodes")

    Internationalization of String Concatenations Concatenation of Localized Strings and User Input

    If an NLS string is not a simple literal but obtained as a concatenation of several values, always use MessageFormat pattern to extract it to a message bundle.

    For example, to internationalize "Delete Class " + className add the following property:

    title.delete.class=Delete Class {0}

    and access it with message("title.delete.class", className) in the client code.

    Patterns should be used even if the changing part of the string is the last or the first element in the concatenation, because this may change when the message is translated to a language with a different grammar.

    Note that single quotes are used for escaping in MessageFormat patterns, and to use ' character it is required to double it: ''.

    For example, below are the correct sentences:

    # single quote in the value below is not escaped, # because MessageFormat pattern is not used: checkbox.text.do.not.show.again=Don't show again # single quote in the value below is escaped, # because MessageFormat pattern is used (notice "{0}"): error.message.file.does.not.exist=File {0} doesn''t exist

    Avoid Composing NLS Strings from Parts

    If it is required to include a dynamically obtained string in a message, it is necessary to use message patterns as described above. However, in other cases, it is better to avoid composing NLS strings from smaller parts stored in separate properties:

    The following example won't be translated correctly into the languages which use word cases:

    English messages:

    dialog.title.add.0=Add {0} dialog.title.edit.0=Edit {0} dialog.title.name.0.1={0} ''{1}'' concept.library=Library concept.dependency=Dependency

    Polish translations:

    dialog.title.add.0=Dodaj {0} dialog.title.add.0=Edytuj {0} concept.library=Bibilioteka concept.dependency=Zależność

    Correct result:

    message("dialog.title.name.0.1", message("concept.library"), "foo") // Biblioteka 'foo'

    Wrong result:

    message("dialog.title.add.0", message("concept.library")) // Dodaj Biblioteka // wrong case and capitalization (correct: "Dodaj bibliotekę")

    If several localized strings (non-user input) are used to concatenate the string, then the following techniques can be used (in order of preference):

    1. Consider reworking the UI to avoid the string concatenation (consult the UX expert if your organization has any, or check IntelliJ Platform UI Guidelines).

    2. Rephrase the string.

    3. Provide the whole string for each context and term pair:

      dialog.title.add.library=Add Library dialog.title.edit.library=Edit Library dialog.title.name.library.0=Library ''{0}'' dialog.title.add.dependency=Add Dependency dialog.title.edit.dependency=Edit Dependency dialog.title.name.dependency.0=Dependency ''{0}''

      This approach is the least preferred:

    Messages Depending on Numbers

    Sometimes it is required to change a message depending on a number, for example, to pluralize a noun or use a proper form for a verb. In that case, use ChoiceFormat patterns.

    It starts with an index of the argument which will be used for choosing a variant, then the choice word follows, and the rest specifies pairs of numbers and corresponding values separated by |.

    For example, for pattern:

    title.selected.files=Selected {0,choice,1#File|2#Files}

    the expression message("title.selected.files", count) will evaluate to:

    The number before # characters does not specify the exact value but start of the range. The corresponding variant will be used if the argument is greater or equal to the number in this clause and less than the number in the next clause. For example, for pattern:

    label.selected.files={0,choice,0#No files are|1#One file is|2#A few files are|10#Many files are} selected

    the expression message("label.selected.files", 6) will evaluate to "A few files are selected".

    If an argument is referred in one of the choice's variants, it becomes a message pattern itself, and this adds additional layer of escaping of single quotes, so to add ' character in such a variant, add: ''''. For example, below is the correct sentence:

    warning.message={0,choice,1#One person doesn''t|2#{0} people don''''t} like MessageFormat

    In some cases, the ordinal format can be useful. It adds an appropriate ending to numbers, so it turns into 1st, 2nd, 3rd, 10th, and so on:

    parameter.cast.fix=Cast {0,number,ordinal} parameter to {1}

    Formatting Non-Textual Values

    Different countries and languages display numbers, dates and times, durations, file sizes, and other values, in a localized way. The IntelliJ Platform provides some utils to display them properly.

    Date and Time Durations File Sizes

    If a topic is not covered in the above sections, let us know via the Was this page helpful? feedback form below or other channels.

    Be specific about the topics and reasons for adding them and leave your email in case we need more details. Thanks for your feedback!

    05 August 2025


    RetroSearch is an open source project built by @garambo | Open a GitHub Issue

    Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

    HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4