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 Original line Diff line number Diff line
@@ -41,6 +41,15 @@ typedef enum Command {
    kCommandSingleCrunch,
    kCommandSingleCrunch,
} Command;
} Command;


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

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


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


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


        String8 part(p, q-p);
        String8 part(p, q-p);


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


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


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


    ResTable_config pseudoParams(curParams);
    ResTable_config pseudoParams(curParams);
        pseudoParams.language[0] = 'z';
        pseudoParams.language[0] = 'e';
        pseudoParams.language[1] = 'z';
        pseudoParams.language[1] = 'n';
        pseudoParams.country[0] = 'Z';
        pseudoParams.country[0] = 'X';
        pseudoParams.country[1] = 'Z';
        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) {
    while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
        if (code == ResXMLTree::START_TAG) {
        if (code == ResXMLTree::START_TAG) {
@@ -1334,6 +1340,7 @@ status_t compileResourceFile(Bundle* bundle,
                                name,
                                name,
                                locale,
                                locale,
                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
                                SourcePos(in->getPrintableSource(), block.getLineNumber()));
                        curIsPseudolocalizable = fileIsTranslatable;
                    }
                    }


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


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

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


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


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


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