javaandroidxmlinternationalizationxliff

Internationalization in Android (Java), use default values of xliff:g in layouts (XML)


I started with internationalization in Android with i18n I guess (by default in Android Studio). But, I have a major problem. My application needed to be able to inject variables in my strings, so I took care to use as I had seen on the official documentation of Android, that we could do this with the tag <xliff:g>. The example attribute works very well when we use this String in Java, with getString, but loses all efficiency when we use this same variable in its XML activity layout.

For example, this strings.xml file is used for the translation :

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="starting">Start: <xliff:g id="unknown_position" example="Unknown position">%1$s</xliff:g>.</string>
    <string name="end">Arrival: <xliff:g id="unknown_position" example="Unknown position">%1$s</xliff:g>.</string>
    <string name="beginning_default">• Beginning: <xliff:g id="unknown_start_date" example="21 august 2022 at 14h21">%1$s</xliff:g></string>
    <string name="ending_default">• End: <xliff:g id="unknown_end_date" example="22 august 2022 at 14h20">%1$s</xliff:g></string>
</resources>

I use theses variables in my activity_layout.xml file:

        <TextView
            android:id="@+id/startPositionText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:text="@string/starting"
            android:textColor="@color/white"
            android:textSize="20sp"
            />

        <TextView
            android:id="@+id/endPositionText"
            android:layout_below="@id/startPositionText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:text="@string/end"
            android:textColor="@color/white"
            android:textSize="20sp"
            />

        <TextView
            android:id="@+id/startText"
            android:layout_below="@+id/endPositionText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/beginning_default"
            android:textColor="@color/white"
            android:textSize="17sp"
            />

        <TextView
            android:id="@+id/endText"
            android:layout_below="@id/startText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/ending_default"
            android:textColor="@color/white"
            android:textSize="17sp"
            />

But, I've the following result :

problems

Do you know how I can solve this problem ? And why does this happen?

I thank you in advance, and wish you a good day!


Solution

  • The <xliff:g> tags are not preserved at runtime.
    They are only useful in the translation phase. They protect the text in-between, so that translators don't damage the %1$s and so on, and they give extra context to the translators (through the ID and example), so that they know what that is going to be there in the end.

    But the tags are dropped when the resources are compiled.

    So this is what you have visible at runtime:

    starting = "Start: %1$s."
    end = "Arrival: %1$s."
    beginning_default="• Beginning: %1$s"
    ending_default="• End: %1$s"
    

    Note that all you have are positional parameters.

    When you call these from code you probably do something like this:

    String text = resources.getString(R.string.beginning_default, startDate);
    

    You provide a parameter that is is formatted and replaces the %1$s.
    But when you use the string in the layout there are no parameters, and %1$s is left "as is".