Skip to content

Commit

Permalink
completion & patch bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
ArrayIterator committed Oct 17, 2024
1 parent 6b866a5 commit f622dc4
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 82 deletions.
6 changes: 1 addition & 5 deletions examples/example.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,14 @@
<content-type>text/plain; charset=UTF-8</content-type>
<content-transfer-encoding>8bit</content-transfer-encoding>
<plural-forms>nplurals=2; plural=(n != 1);</plural-forms>
<custom-header>
<item name="custom-header">Custom Header</item>
<item name="custom-header2">Custom Header 2</item>
</custom-header>
</headers>
<translations>
<context name="">
<item>
<comments>
<item>This is a comment for the translator as a string.</item>
</comments>
<disabled/>
<enable/>
<msgid>as a key reference</msgid>
<msgid_plural/>
<msgstr>
Expand Down
33 changes: 30 additions & 3 deletions src/Gettext/Generator/XMLGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,38 @@ export default class XMLGenerator implements GettextGeneratorInterface {
<!-- revision="${translations.revision}"-->
<!-->-->
<translation revision="${translations.revision}">
<title>Translation for language : ${translations.language}</title>
<description>Translation for language : ${translations.language}</description>
\n`);
const spaces = ' '.repeat(4);

let comments = translations.attributes.comments.all;
let title : string = `Translation for language : ${translations.language}`;
let description : string = `The translation for the language : ${translations.language}`;
for (let i = 0; i < comments.length; i++) {
if (comments[i].startsWith('<title>')) {
let match = comments[i].match(/^<title>(.*)<\/title>/);
if (match) {
title = match[1].trim() || title;
} else {
//strip the title tag
title = comments[i].replace(/<[^>]+>/g, '').trim() || title;
}
comments.splice(i, 1);
continue;
}
if (comments[i].startsWith('<description>')) {
let match = comments[i].match(/^<description>(.*)<\/description>/);
if (match) {
description = match[1].trim() || description;
} else {
//strip the description tag
description = comments[i].replace(/<[^>]+>/g, '').trim() || description;
}
comments.splice(i, 1);
}
}

stream.write(`${spaces}<title>${encode_entities(title)}</title>\n`);
stream.write(`${spaces}<description>${encode_entities(description)}</description>\n`);
if (translations.attributes.flags.length > 0) {
let content: string[] = [`${spaces}<flags>`];
translations.attributes.flags.forEach((flag: string) => {
Expand All @@ -63,7 +90,7 @@ export default class XMLGenerator implements GettextGeneratorInterface {
content.push(`${spaces}</references>`);
stream.write(content.join('\n') + '\n');
}
if (translations.attributes.comments.length > 0) {
if (comments.length > 0) {
let content: string[] = [`${spaces}<comments>`];
translations.attributes.comments.forEach((comment: string) => {
comment = encode_entities(comment);
Expand Down
20 changes: 11 additions & 9 deletions src/Gettext/Metadata/Headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ export default class Headers implements GettextHeadersInterface {
* @inheritDoc
*/
public setFallbackLanguage(language: string): void {
let locale = normalizeLocale(language);
if (locale) {
this.#fallbackLanguage = language;
let info = getLocaleInfo(language);
if (info) {
this.#fallbackLanguage = info.id;
}
}

Expand Down Expand Up @@ -326,12 +326,14 @@ export default class Headers implements GettextHeadersInterface {
this.#headers[normalizedName] = this.pluralForm.header;
break;
case HEADER_LANGUAGE_KEY:
let locale = normalizeLocale(value);
if (locale) {
let info = getLocaleInfo(locale);
this.#headers[normalizedName] = info ? info.id : locale;
if (info) {
this.#headers[HEADER_LANGUAGE_NAME_KEY] = info.name;
let localeInfo = getLocaleInfo(value);
if (localeInfo) {
this.#headers[normalizedName] = localeInfo.id;
this.#headers[HEADER_LANGUAGE_NAME_KEY] = localeInfo.name;
} else {
let language = normalizeLocale(value);
if (language) {
this.#headers[normalizedName] = language;
}
}
break;
Expand Down
23 changes: 17 additions & 6 deletions src/Gettext/Reader/XMLReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,14 @@ import {
* <content-type>text/plain; charset=UTF-8</content-type>
* <content-transfer-encoding>8bit</content-transfer-encoding>
* <plural-forms>nplurals=2; plural=(n != 1);</plural-forms>
* <custom-header>
* <item name="custom-header">Custom Header</item>
* <item name="custom-header2">Custom Header 2</item>
* </custom-header>
* </headers>
* <translations>
* <context name="">
* <item>
* <comments>
* <item>This is a comment for the translator as a string.</item>
* </comments>
* <disabled/>
* <enable/>
* <msgid>as a key reference</msgid>
* <msgid_plural/>
* <msgstr>
Expand Down Expand Up @@ -175,7 +171,14 @@ export default class XMLReader implements GettextReaderInterface{
);
}
const translations = new GettextTranslations<GettextTranslationType, GettextTranslationsType>(parseInt(revision + ''));

let title = rootFilter('title', rootElement.children).map((node) => node.textContent)[0];
if (is_string(title)) {
translations.attributes.comments.add('<title>' + this.cleanData(title) + '</title>');
}
let description = rootFilter('description', rootElement.children).map((node) => node.textContent)[0];
if (is_string(description)) {
translations.attributes.comments.add('<description>' + this.cleanData(description) + '</description>');
}
rootFilter('headers', rootElement.children).forEach((headerElement) : void => {
for (let child in headerElement.children) {
const node = headerElement.children[child];
Expand Down Expand Up @@ -265,6 +268,14 @@ export default class XMLReader implements GettextReaderInterface{
`The translation is not valid, ${(e as Error).message}`
);
}

let disabled = rootFilter('enable', itemElement?.children).map((node) => node.textContent)[0];
if (is_string(disabled)) {
disabled = disabled.trim().toLowerCase();
if (disabled === 'false' || disabled === '0') {
gettextTranslation.setEnabled(false);
}
}
// append translation
translations.add(gettextTranslation);
// <comments> > <item>+
Expand Down
50 changes: 33 additions & 17 deletions src/Schema/translation.xsd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.1" elementFormDefault="qualified" version="1.1">
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
<xs:annotation>
<xs:documentation>
The Gettext XML Schema is used to validate the structure of a Gettext translation file.
Expand All @@ -9,7 +9,7 @@
<!-- attribute flags -->
<xs:complexType name="FlagsType">
<xs:sequence>
<xs:element name="item" type="xs:string" maxOccurs="unbounded" minOccurs="0">
<xs:element name="item" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation>The flags used to mark the translation file. The flag is case-insensitive.</xs:documentation>
</xs:annotation>
Expand All @@ -25,13 +25,13 @@
<!-- attribute references -->
<xs:complexType name="ReferencesType">
<xs:sequence>
<xs:element name="item" type="xs:string" maxOccurs="unbounded" minOccurs="0">
<xs:element name="item" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation>The references used to identify the original source of the translations.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="^[^:]+(:(?:0|[1-9][0-9]*))?"/>
<xs:pattern value="[^:]+(:(0|[0-9][0-9])*)?"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Expand All @@ -41,24 +41,38 @@
<!-- attribute comments -->
<xs:complexType name="CommentsType">
<xs:sequence>
<xs:element name="item" type="xs:string" maxOccurs="unbounded" minOccurs="0">
<xs:element name="item" maxOccurs="unbounded" minOccurs="0">
<xs:annotation>
<xs:documentation>The comments used to provide additional information about the translation file.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>

<!-- attribute header -->
<xs:complexType name="HeaderType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:NCName" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>

<!-- start translation / root -->
<xs:element name="translation">
<xs:complexType>
<xs:all>
<xs:element name="title" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>The title of the translation file.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="description" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation>The domain of the translation file.</xs:documentation>
</xs:annotation>
</xs:element>
<!-- attributes -->
<xs:element name="flags" type="FlagsType" minOccurs="0">
<xs:unique name="uniqueFlag">
<xs:selector xpath="item"/>
Expand All @@ -68,6 +82,7 @@
<xs:element name="references" type="ReferencesType" minOccurs="0"/>
<xs:element name="comments" type="CommentsType" minOccurs="0"/>
<xs:element name="extracted-comments" type="CommentsType" minOccurs="0"/>

<!-- headers -->
<xs:element name="headers" minOccurs="0">
<xs:complexType>
Expand All @@ -92,7 +107,7 @@
<xs:documentation>The last-translator key is the name and email address of the last translator.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="language" type="xs:string">
<xs:element name="language">
<xs:annotation>
<xs:documentation>The language key is the language code of the translation.</xs:documentation>
</xs:annotation>
Expand All @@ -117,7 +132,7 @@
<xs:documentation>The mime-version key is the MIME version of the translation file.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="content-type" type="xs:string" minOccurs="0">
<xs:element name="content-type" minOccurs="0">
<xs:annotation>
<xs:documentation>The content-type key is the content type of the translation file.</xs:documentation>
</xs:annotation>
Expand All @@ -127,7 +142,7 @@
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="content-transfer-encoding" type="xs:string" minOccurs="0">
<xs:element name="content-transfer-encoding" minOccurs="0">
<xs:annotation>
<xs:documentation>The content-transfer-encoding key is the content transfer encoding of the translation file.</xs:documentation>
</xs:annotation>
Expand All @@ -141,7 +156,7 @@
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="plural-forms" type="xs:string" minOccurs="0">
<xs:element name="plural-forms" minOccurs="0">
<xs:annotation>
<xs:documentation>The plural-forms key is the plural forms of the translation file.</xs:documentation>
</xs:annotation>
Expand All @@ -151,7 +166,7 @@
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="custom-header" minOccurs="0" maxOccurs="1">
<xs:element name="custom-header" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="item" type="HeaderType" maxOccurs="unbounded"/>
Expand All @@ -178,7 +193,7 @@
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:all>
<xs:element name="comments" type="CommentsType" minOccurs="0"/>
<xs:element name="extracted-comments" minOccurs="0">
<xs:complexType>
Expand All @@ -194,10 +209,11 @@
<xs:field xpath="."/>
</xs:unique>
</xs:element>
<xs:choice>
<xs:element name="enable" minOccurs="0"/>
<xs:element name="disabled" minOccurs="0"/>
</xs:choice>
<xs:element name="enable" minOccurs="0" type="xs:boolean" default="true">
<xs:annotation>
<xs:documentation>The enable key is used to enable or disable the translation.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="msgid" type="xs:string"/>
<xs:element name="msgid_plural" type="xs:string" minOccurs="0"/>
<xs:element name="msgstr">
Expand All @@ -207,7 +223,7 @@
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
Expand All @@ -223,7 +239,7 @@
</xs:element>
</xs:all>
<!-- attributes -->
<xs:attribute name="revision" type="xs:integer" default="0" xml:space="preserve">
<xs:attribute name="revision" type="xs:unsignedInt" default="0" xml:space="preserve">
<xs:annotation>
<xs:documentation>The revision number of the translation file.</xs:documentation>
</xs:annotation>
Expand Down
27 changes: 3 additions & 24 deletions src/Translations/Translator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import TranslationEntriesInterface from './Interfaces/TranslationEntriesInterfac
import {
DEFAULT_DOMAIN,
DEFAULT_LANGUAGE,
getLocaleInfo,
normalizeLocale
} from '../Utils/Locale';
import {
Expand All @@ -16,26 +15,6 @@ import TranslationEntryInterface from './Interfaces/TranslationEntryInterface';
import TranslationEntries from './TranslationEntries';
import GettextTranslationInterface from '../Gettext/Interfaces/GettextTranslationInterface';

/**
* Filter the language
*
* @param language
*/
export const filter_language = (language: string): string | null => {
if (!is_string(language)) {
return null;
}
let info = getLocaleInfo(language);
if (info) {
return info.id;
}
let locale = normalizeLocale(language);
if (locale) {
return locale;
}
return null;
}

/**
* The translator
*/
Expand Down Expand Up @@ -82,7 +61,7 @@ export default class Translator<
* @inheritDoc
*/
public setOriginalLanguage(language: string): string | undefined {
let locale = filter_language(language);
let locale = normalizeLocale(language);
if (!locale) {
return undefined;
}
Expand Down Expand Up @@ -115,7 +94,7 @@ export default class Translator<
* @inheritDoc
*/
public setLanguage(language: string) : string|undefined {
let locale = filter_language(language);
let locale = normalizeLocale(language);
if (!locale) {
return undefined;
}
Expand Down Expand Up @@ -163,7 +142,7 @@ export default class Translator<
if (!language) {
language = translations.headers.language;
}
let locale = filter_language(language);
let locale = normalizeLocale(language);
if (!locale) { // empty skipped
return false;
}
Expand Down
Loading

0 comments on commit f622dc4

Please sign in to comment.