Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2ef5c0d authored by Anton Krumin's avatar Anton Krumin
Browse files

Pseudolocalizer improvements.



Fixes accented pseudolocalization and adds RTL pseudolocale.

This change contains following modifications in the pseudolocalization logic:
1) zz_ZZ pseudolocale was removed;
2) en_XA pseudolocale was added for pseudo-accented;
3) ar_XB pseudolocale was added for pseudo-rtl;
4) Pseudo RTL localization functionality was implemented;
5) Text expansion functionality was implemented;
6) Text bracketing was implemented;
7) Couple of issues of previous implementation were fixed.

Change-Id: I9f7f27bed717e39e82717d15c398decffc8bec3c
Signed-off-by: default avatarAnton Krumin <antkrumin@google.com>
parent ecdf9b19
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -41,6 +41,15 @@ typedef enum Command {
    kCommandSingleCrunch,
} Command;

/*
 * Pseudolocalization methods
 */
typedef enum PseudolocalizationMethod {
    NO_PSEUDOLOCALIZATION = 0,
    PSEUDO_ACCENTED,
    PSEUDO_BIDI,
} PseudolocalizationMethod;

/*
 * Bundle of goodies, including everything specified on the command line.
 */
@@ -50,7 +59,7 @@ public:
        : mCmd(kCommandUnknown), mVerbose(false), mAndroidList(false),
          mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false),
          mUpdate(false), mExtending(false),
          mRequireLocalization(false), mPseudolocalize(false),
          mRequireLocalization(false), mPseudolocalize(NO_PSEUDOLOCALIZATION),
          mWantUTF16(false), mValues(false),
          mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
          mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
@@ -94,8 +103,8 @@ public:
    void setExtending(bool val) { mExtending = val; }
    bool getRequireLocalization(void) const { return mRequireLocalization; }
    void setRequireLocalization(bool val) { mRequireLocalization = val; }
    bool getPseudolocalize(void) const { return mPseudolocalize; }
    void setPseudolocalize(bool val) { mPseudolocalize = val; }
    short getPseudolocalize(void) const { return mPseudolocalize; }
    void setPseudolocalize(short val) { mPseudolocalize = val; }
    void setWantUTF16(bool val) { mWantUTF16 = val; }
    bool getValues(void) const { return mValues; }
    void setValues(bool val) { mValues = val; }
@@ -250,7 +259,7 @@ private:
    bool        mUpdate;
    bool        mExtending;
    bool        mRequireLocalization;
    bool        mPseudolocalize;
    short       mPseudolocalize;
    bool        mWantUTF16;
    bool        mValues;
    int         mCompressionMethod;
+5 −2
Original line number Diff line number Diff line
@@ -1885,14 +1885,17 @@ int doPackage(Bundle* bundle)
    FILE* fp;
    String8 dependencyFile;

    // -c zz_ZZ means do pseudolocalization
    // -c en_XA or/and ar_XB means do pseudolocalization
    ResourceFilter filter;
    err = filter.parse(bundle->getConfigurations());
    if (err != NO_ERROR) {
        goto bail;
    }
    if (filter.containsPseudo()) {
        bundle->setPseudolocalize(true);
        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
    }
    if (filter.containsPseudoBidi()) {
        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
    }

    N = bundle->getFileSpecCount();
+4 −2
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@ ResourceFilter::parse(const char* arg)

        String8 part(p, q-p);

        if (part == "zz_ZZ") {
            mContainsPseudo = true;
        if (part == "en_XA") {
            mContainsPseudoAccented = true;
        } else if (part == "ar_XB") {
            mContainsPseudoBidi = true;
        }
        int axis;
        AxisValue value;
+6 −3
Original line number Diff line number Diff line
@@ -16,19 +16,22 @@
class ResourceFilter
{
public:
    ResourceFilter() : mData(), mContainsPseudo(false) {}
    ResourceFilter() : mData(), mContainsPseudoAccented(false),
        mContainsPseudoBidi(false) {}
    status_t parse(const char* arg);
    bool isEmpty() const;
    bool match(int axis, const ResTable_config& config) const;
    bool match(const ResTable_config& config) const;
    const SortedVector<AxisValue>* configsForAxis(int axis) const;
    inline bool containsPseudo() const { return mContainsPseudo; }
    inline bool containsPseudo() const { return mContainsPseudoAccented; }
    inline bool containsPseudoBidi() const { return mContainsPseudoBidi; }

private:
    bool match(int axis, const AxisValue& value) const;

    KeyedVector<int,SortedVector<AxisValue> > mData;
    bool mContainsPseudo;
    bool mContainsPseudoAccented;
    bool mContainsPseudoBidi;
};

#endif
+61 −33
Original line number Diff line number Diff line
@@ -577,7 +577,7 @@ status_t parseAndAddBag(Bundle* bundle,
                        int32_t curFormat,
                        bool isFormatted,
                        const String16& product,
                        bool pseudolocalize,
                        PseudolocalizationMethod pseudolocalize,
                        const bool overwrite,
                        ResourceTable* outTable)
{
@@ -672,7 +672,7 @@ status_t parseAndAddEntry(Bundle* bundle,
                        int32_t curFormat,
                        bool isFormatted,
                        const String16& product,
                        bool pseudolocalize,
                        PseudolocalizationMethod pseudolocalize,
                        const bool overwrite,
                        KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
                        ResourceTable* outTable)
@@ -854,10 +854,16 @@ status_t compileResourceFile(Bundle* bundle,
    ResTable_config curParams(defParams);

    ResTable_config pseudoParams(curParams);
        pseudoParams.language[0] = 'z';
        pseudoParams.language[1] = 'z';
        pseudoParams.country[0] = 'Z';
        pseudoParams.country[1] = 'Z';
        pseudoParams.language[0] = 'e';
        pseudoParams.language[1] = 'n';
        pseudoParams.country[0] = 'X';
        pseudoParams.country[1] = 'A';

    ResTable_config pseudoBidiParams(curParams);
        pseudoBidiParams.language[0] = 'a';
        pseudoBidiParams.language[1] = 'r';
        pseudoBidiParams.country[0] = 'X';
        pseudoBidiParams.country[1] = 'B';

    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
        if (code == ResXMLTree::START_TAG) {
@@ -1334,6 +1340,7 @@ status_t compileResourceFile(Bundle* bundle,
                                name,
                                locale,
                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
                        curIsPseudolocalizable = fileIsTranslatable;
                    }

                    if (formatted == false16) {
@@ -1389,6 +1396,7 @@ status_t compileResourceFile(Bundle* bundle,
                curTag = &plurals16;
                curType = plurals16;
                curIsBag = true;
                curIsPseudolocalizable = fileIsTranslatable;
            } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
                curTag = &array16;
                curType = array16;
@@ -1410,25 +1418,23 @@ status_t compileResourceFile(Bundle* bundle,
            } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
                // Check whether these strings need valid formats.
                // (simplified form of what string16 does above)
                bool isTranslatable = false;
                size_t n = block.getAttributeCount();

                // Pseudolocalizable by default, unless this string array isn't
                // translatable.
                curIsPseudolocalizable = true;
                for (size_t i = 0; i < n; i++) {
                    size_t length;
                    const uint16_t* attr = block.getAttributeName(i, &length);
                    if (strcmp16(attr, translatable16.string()) == 0) {
                    if (strcmp16(attr, formatted16.string()) == 0) {
                        const uint16_t* value = block.getAttributeStringValue(i, &length);
                        if (strcmp16(value, false16.string()) == 0) {
                            curIsPseudolocalizable = false;
                        }
                            curIsFormatted = false;
                        }

                    if (strcmp16(attr, formatted16.string()) == 0) {
                    } else if (strcmp16(attr, translatable16.string()) == 0) {
                        const uint16_t* value = block.getAttributeStringValue(i, &length);
                        if (strcmp16(value, false16.string()) == 0) {
                            curIsFormatted = false;
                            isTranslatable = false;
                        }
                    }
                }
@@ -1438,6 +1444,7 @@ status_t compileResourceFile(Bundle* bundle,
                curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
                curIsBag = true;
                curIsBagReplaceOnOverwrite = true;
                curIsPseudolocalizable = isTranslatable && fileIsTranslatable;
            } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
                curTag = &integer_array16;
                curType = array16;
@@ -1559,17 +1566,27 @@ status_t compileResourceFile(Bundle* bundle,

                        err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
                                ident, parentIdent, itemIdent, curFormat, curIsFormatted,
                                product, false, overwrite, outTable);
                                product, NO_PSEUDOLOCALIZATION, overwrite, outTable);
                        if (err == NO_ERROR) {
                            if (curIsPseudolocalizable && localeIsDefined(curParams)
                                    && bundle->getPseudolocalize()) {
                                    && bundle->getPseudolocalize() > 0) {
                                // pseudolocalize here
#if 1
                                if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
                                   PSEUDO_ACCENTED) {
                                    block.setPosition(parserPosition);
                                    err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
                                            curType, ident, parentIdent, itemIdent, curFormat,
                                        curIsFormatted, product, true, overwrite, outTable);
#endif
                                            curIsFormatted, product, PSEUDO_ACCENTED,
                                            overwrite, outTable);
                                }
                                if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
                                   PSEUDO_BIDI) {
                                    block.setPosition(parserPosition);
                                    err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage,
                                            curType, ident, parentIdent, itemIdent, curFormat,
                                            curIsFormatted, product, PSEUDO_BIDI,
                                            overwrite, outTable);
                                }
                            }
                        }
                        if (err != NO_ERROR) {
@@ -1592,20 +1609,31 @@ status_t compileResourceFile(Bundle* bundle,

                err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
                        *curTag, curIsStyled, curFormat, curIsFormatted,
                        product, false, overwrite, &skippedResourceNames, outTable);
                        product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable);

                if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
                    hasErrors = localHasErrors = true;
                }
                else if (err == NO_ERROR) {
                    if (curIsPseudolocalizable && localeIsDefined(curParams)
                            && bundle->getPseudolocalize()) {
                            && bundle->getPseudolocalize() > 0) {
                        // pseudolocalize here
                        if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
                           PSEUDO_ACCENTED) {
                            block.setPosition(parserPosition);
                            err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
                                    ident, *curTag, curIsStyled, curFormat,
                                    curIsFormatted, product,
                                true, overwrite, &skippedResourceNames, outTable);
                                    PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable);
                        }
                        if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
                           PSEUDO_BIDI) {
                            block.setPosition(parserPosition);
                            err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams,
                                    myPackage, curType, ident, *curTag, curIsStyled, curFormat,
                                    curIsFormatted, product,
                                    PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable);
                        }
                        if (err != NO_ERROR) {
                            hasErrors = localHasErrors = true;
                        }
@@ -2636,8 +2664,8 @@ ResourceTable::validateLocalizations(void)
                    continue;
                }

                // don't bother with the pseudolocale "zz_ZZ"
                if (config != "zz_ZZ") {
                // don't bother with the pseudolocale "en_XA" or "ar_XB"
                if (config != "en_XA" && config != "ar_XB") {
                    if (configSrcMap.find(config) == configSrcMap.end()) {
                        // okay, no specific localization found.  it's possible that we are
                        // requiring a specific regional localization [e.g. de_DE] but there is an
Loading