diff --git a/locale/en_US/submission.xml b/locale/en_US/submission.xml
index 3fa4daf55db..934716ac944 100644
--- a/locale/en_US/submission.xml
+++ b/locale/en_US/submission.xml
@@ -15,6 +15,7 @@
Provide a formatted list of references for works cited in this submission. Please separate individual references with a blank line.
+
CrossRef Registration Email
Please enter a valid CrossRef registration email. You can register your email for free on the CrossRef web site.
ISBNdb API Key
@@ -27,10 +28,14 @@
Please select one of the given citation modules.
Don't use by default (will still be available to the editor)
Internal error. A non-valid value has been posted for the 'optional filter' setting. Please report this as a bug.
+
+
Authors
For best results, authors should be entered in the following format: Coleman Jr, D. (Ralf) Dr.
Editors
For best results, editors should be entered in the following format: Coleman Jr, D. (Ralf) Dr.
+
+
Article/Paper Title
Please enter a valid article/paper title.
Journal/Book Title
@@ -97,7 +102,24 @@
Please enter a valid annotation.
Publication Type
Please make sure that you always set a publication type. Currently supported values are book (for books or book chapters) and journal (for journal articles). Otherwise the citation output formatting will not work correctly.
+
+
+ Title Type
+ Please make sure that you set a valid title type. Supported values are 'abbreviated', 'translated', 'alternative' and 'uniform'.
+ Part of title ignored while sorting
+ Please only enter the initial characters of the title that should be ignored when sorting the title.
+ Title
+ Please enter a valid title.
+ Subtitle
+ Please enter a valid subtitle.
+ Part Number
+ Please enter a valid part number.
+ Part Name
+ Please enter a valid part name.
+ Name Type
+ Please make sure that you set a valid name type. Supported values are 'personal', 'corporate' and 'conference'.
+
Agencies
Abstract Views
Accepted
diff --git a/plugins/metadata/mods/schema/ModsNameSchema.inc.php b/plugins/metadata/mods/schema/ModsNameSchema.inc.php
new file mode 100644
index 00000000000..4fdf5e399e3
--- /dev/null
+++ b/plugins/metadata/mods/schema/ModsNameSchema.inc.php
@@ -0,0 +1,93 @@
+.
+ *
+ * Wherever possible we follow the "Digital Library Federation / Aquifer
+ * Implementation Guidelines for Shareable MODS Records", see
+ *
+ *
+ * The DLF/Aquifer Implementation Guidelines for Shareable MODS Records
+ * requires the use of at least one name description for the creator of the
+ * intellectual content of the resource, if available. Please use a type
+ * statement with all name descriptions for greater control and interoperability.
+ * In addition at least one namePart statement is a required of each name
+ * description.
+ */
+
+
+import('lib.pkp.classes.metadata.MetadataSchema');
+
+class ModsNameSchema extends MetadataSchema {
+ /**
+ * Constructor
+ */
+ function ModsNameSchema() {
+ // Configure the meta-data schema.
+ parent::MetadataSchema(
+ 'mods-3.4-name',
+ 'mods34',
+ array(ASSOC_TYPE_AUTHOR, ASSOC_TYPE_EDITOR)
+ );
+
+
+ // The type attribute can take the following values: personal,
+ // corporate and conference. This is a required attribute.
+ $this->addProperty('[@type]', array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods34-name-types'), false, METADATA_PROPERTY_CARDINALITY_ONE, 'metadata.property.displayName.name-type', 'metadata.property.validationMessage.name-type', true);
+
+ // The name itself is always wrapped in namePart elements. MODS allows for either
+ // breaking up parts of the name (given and family, for example) in different namePart
+ // elements or enclosing the entire name in one element. Use of the former method affords
+ // more control in sorting and display which is why it is the only encoding supported
+ // in our case.
+
+ // Use the following typeless namePart version for corporate and conference names.
+ $this->addProperty('namePart');
+
+ // Use the following namePart types for personal names.
+ $this->addProperty('namePart[@type="family"]');
+ $this->addProperty('namePart[@type="given"]');
+
+ // The attribute "termsOfAddress" is used to record titles and enumeration associated
+ // with a name, such as Jr., II, etc.
+ $this->addProperty('namePart[@type="termsOfAddress"]');
+
+ // The attribute "date" is used to parse dates that are not integral parts of a name,
+ // i.e. the lifetime of an author ("1901-1983") used to disambiguate an author name.
+ // Dates that are part of a name, e.g. dates within a conference name, do not use this
+ // attribute to separate the date, since it is an integral part of the name string.
+ // This attribute is not used when parsing the components of a corporate name.
+ $this->addProperty('namePart[@type="date"]');
+
+ // The affiliation subelement contains the name, address, etc. of an organization with which the
+ // name entity was associated when the resource was created. If the information is readily
+ // available, it may be included.
+ $this->addProperty('affiliation', METADATA_PROPERTY_TYPE_STRING, true);
+
+ // Use the role element as a wrapper element to contain coded and/or textual description
+ // of the role of the named entity. Use this element primarily with personal names. Repeat role
+ // for each new role. We only support coded roles which can be resolved to textual representations
+ // via the controlled vocabulary "mods34-name-role-roleTerms-marcrelator". See the controlled
+ // vocabulary for details of the allowed entries.
+ // NB: If we want to support various roleTerm types within one role then we'll have to create
+ // a separate meta-data schema for roles. We avoid this complexity for now as we don't have a
+ // use case for this.
+ $this->addProperty('role/roleTerm[@type="code" @authority="marcrelator"]', array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods34-name-role-roleTerms-marcrelator'), false, METADATA_PROPERTY_CARDINALITY_MANY);
+ }
+}
+?>
\ No newline at end of file
diff --git a/plugins/metadata/mods/schema/PKPModsSchema.inc.php b/plugins/metadata/mods/schema/PKPModsSchema.inc.php
new file mode 100644
index 00000000000..435b1777af2
--- /dev/null
+++ b/plugins/metadata/mods/schema/PKPModsSchema.inc.php
@@ -0,0 +1,488 @@
+.
+ *
+ * Wherever possible we follow the "Digital Library Federation / Aquifer
+ * Implementation Guidelines for Shareable MODS Records", see
+ *
+ *
+ * NB: This class is an application agnostic base class to be extended
+ * by application specific versions of the schema configuring this class
+ * via constructor arguments.
+ */
+
+
+import('lib.pkp.classes.metadata.MetadataSchema');
+
+class PKPModsSchema extends MetadataSchema {
+ /**
+ * Constructor
+ * @param $appSpecificAssocType integer
+ * @param $useAuthoritiesForSubject boolean whether the subject is
+ * free text or controlled by vocabularies.
+ */
+ function PKPModsSchema($appSpecificAssocType = null, $useAuthoritiesForSubject = false) {
+ // Configure the meta-data schema.
+ $assocTypes = array(ASSOC_TYPE_CITATION);
+ if (!is_null($appSpecificAssocType)) array_push($assocTypes, $appSpecificAssocType);
+ parent::MetadataSchema(
+ 'mods-3.4',
+ 'mods34',
+ $assocTypes
+ );
+
+
+ //
+ // titleInfo
+ //
+
+ // A word, phrase, character, or group of characters, normally appearing in a resource, that
+ // names it or the work contained in it.
+ //
+ // Titles are an extremely important access point for digital library
+ // resources, and are frequently used in brief record displays to assist
+ // end users in deciding whether to investigate a resource further. As
+ // such, at least one titleInfo description with at least one title
+ // statement is required. Additional titleInfo descriptions should be used to
+ // indicate other titles for the resource. Do not include punctuation
+ // intended to delineate parts of titles separated into various statements
+ // within the titleInfo description.
+
+ // We do not implement titleInfo[@type] as we do not allow repetition of the
+ // titleInfo element. We assume that our titles are always primary titles of
+ // the resource.
+
+ // The nonSort element contains characters, including initial articles, punctuation, and
+ // spaces that appear at the beginning of a title that should be ignored for indexing of titles.
+ // This element must be used when non-sorting characters are present, rather than including
+ // them in the text of the title element.
+ $this->addProperty('titleInfo/nonSort', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_ONE, 'metadata.property.displayName.nonSort', 'metadata.property.validationMessage.nonSort');
+
+ // The title element contains the core title of the resource. At least one
+ // title is required. This element includes all parts of a title not covered
+ // by other sub-elements.
+ $this->addProperty('titleInfo/title', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_ONE, 'metadata.property.displayName.title', 'metadata.property.validationMessage.title', true);
+
+ // The subTitle element is used to record a part of a title deemed secondary to the core
+ // portion. Use this element when a subtitle is present, rather than including the subtitle
+ // in the text of the title element. When using the subTitle element, do not include
+ // punctuation at the end of the title element intended to delineate the title from the
+ // subtitle.
+ $this->addProperty('titleInfo/subTitle', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_ONE, 'metadata.property.displayName.subTitle', 'metadata.property.validationMessage.subTitle');
+
+ // The partNumber element is used for a part or section number of a title. Use this
+ // subelement when a part number is present, rather than including the part number
+ // in the text of the title element. When using the partNumber element, do not include
+ // punctuation at the end of the preceding element intended to delineate the part
+ // number from previous parts of the title. Multiple parts of an item should appear
+ // in separate MODS records or relatedItem elements.
+ $this->addProperty('titleInfo/partNumber', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_ONE, 'metadata.property.displayName.partNumber', 'metadata.property.validationMessage.partNumber');
+
+ // The partName element is used for a part or section name of a title. Multiple partName
+ // elements may be nested in a single titleInfo to describe a single part with multiple
+ // hierarchical levels; multiple parts, however, should be separated into multiple
+ // titleInfo elements. Use this subelement when a part name is present, rather than
+ // including the part name in the text of the title element. When using the partName
+ // element, do not include punctuation at the end of the preceding element intended
+ // to delineate the part name from previous parts of the title. Multiple parts of an
+ // item should appear in separate MODS records or relatedItem elements.
+ $this->addProperty('titleInfo/partName', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_ONE, 'metadata.property.displayName.partName', 'metadata.property.validationMessage.partName');
+
+
+ //
+ // name
+ //
+
+ // The DLF/Aquifer Implementation Guidelines for Shareable MODS Records
+ // requires the use of at least one name description for the creator of the
+ // intellectual content of the resource.
+ $personResources = array(
+ array(METADATA_PROPERTY_TYPE_COMPOSITE => ASSOC_TYPE_AUTHOR),
+ array(METADATA_PROPERTY_TYPE_COMPOSITE => ASSOC_TYPE_EDITOR)
+ );
+ $this->addProperty('name', $personResources, false, METADATA_PROPERTY_CARDINALITY_MANY, null, null, true);
+
+
+ //
+ // typeOfResource
+ //
+
+ // A term that specifies the characteristics and general type of content of the resource.
+ // The DLF/Aquifer Implementation Guidelines for Shareable MODS Records require the
+ // use in all records of at least one typeOfResource statement using the required
+ // enumerated values (see the controlled vocabulary).
+ $this->addProperty('typeOfResource', array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods43-typeOfResource'), false, METADATA_PROPERTY_CARDINALITY_ONE, null, null, true);
+
+
+ //
+ // genre
+ //
+
+ // A term that designates a category characterizing a particular style, form, or content,
+ // such as artistic, musical, literary composition, etc. genre contains terms that give more
+ // specificity than the broad terms used in typeOfResource (see the controlled vocabulary).
+ $this->addProperty('genre[@authority="marcgt"]', array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods43-genre-marcgt'), false, METADATA_PROPERTY_CARDINALITY_ONE, null, null, true);
+
+
+ //
+ // originInfo
+ //
+
+ // The originInfo contains information about the origin of the resource,
+ // including place of origin or publication, publisher/originator, and
+ // dates associated with the resource.
+ //
+ // Encode information in originInfo relevant to any version of a resource
+ // that is considered useful for a given metadata use case. It is usually not
+ // necessary to include full originInfo for every version of a resource known
+ // to exist; choose carefully which versions and elements it is important
+ // to share in the context of your metadata use case.
+ //
+ // The DLF/Aquifer Implementation Guidelines for Shareable MODS Records require the
+ // use of at least one originInfo statement with at least one date subelement in every
+ // record, one of which must be marked as a key date. Place, publisher, and
+ // edition are recommended if applicable. This element is repeatable.
+
+ // Record in place/placeTerm place names associated with the
+ // creation or issuance of a resource. Descriptive standards such as AACR2
+ // may be used to determine which places to record for published
+ // resources. For unpublished resources, if a place of origin is known,
+ // record it in place/placeTerm.
+ // The place/placeTerm element should be omitted if no information about
+ // the originating place of the resource is known. Repeat place for recording
+ // multiple places.
+
+ // This is a text-encoded place name (usually the publisher's place description)
+ $this->addProperty('originInfo/place/placeTerm[@type="text"]');
+
+ // This is an ISO 3166 country name (usually the publisher's country).
+ // NB: We could use a vocabulary for country names here. We avoid this for now as
+ // the list would be huge.
+ // See
+ // for a full list.
+ $this->addProperty('originInfo/place/placeTerm[@type="code" @authority="iso3166"]');
+
+ // Record in publisher a named entity determined to be the publisher or originator for a
+ // resource. Descriptive standards such as AACR2 may be used to format the name of the
+ // publisher. Information about an institution responsible for digitizing and delivering
+ // online a previously published resource should be included as a note, rather than
+ // originInfo/publisher.
+ $this->addProperty('originInfo/publisher');
+
+ // The MODS schema includes several date elements intended to record different events
+ // that may be important in the life of a resource. Record dates for as many of these
+ // MODS elements as is appropriate. To indicate to users which is the best date to use
+ // for sorting and similar features, we mark the publication date (dateIssued) as a
+ // key date using the keyDate="yes" attribute. You may choose to use only one date
+ // element when several apply but would contain identical data.
+ // The guidelines recommend recording each date in a structured form rather than a textual
+ // form. We use W3CDTF encoding (YYYY[-MM[-DD]]) throughout.
+
+ // publication or issued date
+ $this->addProperty('originInfo/dateIssued[@keyDate="yes" @encoding="w3cdtf"]', METADATA_PROPERTY_TYPE_DATE);
+
+ // date of creation of the resource
+ $this->addProperty('originInfo/dateCreated[@encoding="w3cdtf"]', METADATA_PROPERTY_TYPE_DATE);
+
+ // date on which a resource is copyrighted
+ $this->addProperty('originInfo/copyrightDate[@encoding="w3cdtf"]', METADATA_PROPERTY_TYPE_DATE);
+
+ // The edition element is used to provide an edition statement for a published work.
+ // Descriptive standards such as AACR2 and DACS may be used to determine if an edition
+ // statement should be recorded and in what format. If no edition statement applies to the
+ // resource, do not include the edition element.
+ $this->addProperty('originInfo/edition', METADATA_PROPERTY_TYPE_STRING, true);
+
+
+ //
+ // language
+ //
+
+ // At least one language/languageTerm element is required for resources in which
+ // language is primary to understanding the resource. The language element is optional
+ // for resources in which language is important to understanding the resource, but not
+ // primary. For example, the caption of a photograph may in some instances be important
+ // to understanding the photograph, but not primary. Whether to include a language
+ // element based on the language's importance or primacy is left to the user's discretion.
+ // Repeat the language element as necessary.
+ $this->addProperty('language[@objectPart=""]/languageTerm[@type="code" @authority="iso639-2b"]', array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods43-typeOfResource'), false, METADATA_PROPERTY_CARDINALITY_MANY, null, null, true);
+
+
+ //
+ // physicalDescription
+ //
+
+ // physicalDescription is a wrapper element that contains all subelements relating to
+ // physical description information of the resource described.
+ //
+ // Encode information in physicalDescription relevant to any version of a resource
+ // that is considered useful for a metadata use case. It is usually not necessary to
+ // include a full physicalDescription for every version of a resource known to exist;
+ // choose carefully which versions and elements are important for your metadata use
+ // case.
+
+ // This subelement specifies the physical form or medium of the material for a resource.
+ $this->addProperty('physicalDescription/form[@authority="marcform"]', array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods34-physicalDescription-form-marcform'));
+
+ // This subelement records the electronic format type of the digital resource. Whenever
+ // a records describe resources existing in digital versions, at least one internetMediaType
+ // is required. This element has no attributes.
+ // Inclusion of an internetMediaType is a key feature of a shared metadata record to
+ // enable external users to provide added value on resources themselves rather than only on
+ // metadata.
+ // The content value for this subelement should be taken from the MIME Media Types list
+ // and expressed in the format type/subtype. If a digital resource comprises multiple file
+ // types (for example PDF and HTML full text), use a separate internetMediaType subelement
+ // for each.
+ // NB: We could use a vocabulary for MIME types here. We avoid this for now as
+ // the list would be huge. See
+ // for a full list.
+ $this->addProperty('physicalDescription/internetMediaType');
+
+ // We use the extent field for the number of pages of a book only.
+ $this->addProperty('physicalDescription/extent', METADATA_PROPERTY_TYPE_INTEGER);
+
+
+ //
+ // abstract
+ //
+
+ // A summary of the content of the resource.
+ // The DLF/Aquifer Implementation Guidelines for Shareable MODS Records recommend
+ // the use of one abstract element in every MODS record, except when a title, formal or
+ // supplied, serves as an adequate summary of the content of the digital resource. This
+ // element is repeatable.
+ $this->addProperty('abstract', METADATA_PROPERTY_TYPE_STRING, true);
+
+
+ //
+ // note
+ //
+
+ // General textual information relating to a resource.
+ $this->addProperty('note', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_MANY);
+
+
+ //
+ // subject
+ //
+
+ // A subject is a term or phrase representing the primary topic(s) on which
+ // a work is focused.
+ //
+ // Information in subject describes subject content represented in or by the work, and
+ // typically answers such questions as who, what, where, and when.
+ // Whether or not the use of subject is applicable depends upon who might search for an
+ // item outside its local context and how they are likely to search for it. For instance, topical
+ // subject content may not apply to some items, such as abstract art. If researchers are likely
+ // to be interested in the form or genre of an item, and not its subject content, using the
+ // genre element (not the subelement under subject) may be most appropriate.
+ //
+ // However, in many instances, using appropriate subject values can greatly enhance
+ // users’ ability to locate relevant works. Enter as many specific terms as necessary to
+ // capture subject content, and be consistent in the formatting of subject terms.
+ //
+ // It is highly recommended that subject terms come from a controlled vocabulary or formal
+ // classification scheme and that this source is identified in the authority attribute. Select
+ // controlled vocabularies that are most relevant to and frequently used by the communities
+ // likely to benefit from the described materials, and explicitly identify this source.
+ //
+ // Express multiple subjects in repeated subject fields.
+
+ // Will we use controlled vocabularies to validate subjects?
+ if ($useAuthoritiesForSubject) {
+ // The name of the authoritative list that controls all statements in this
+ // description is recorded here. An authority attribute may also be used to indicate
+ // that a subject is controlled by a record in an authority file. Authority should be
+ // specified for all terms, whether they come from a controlled vocabulary, formal
+ // scheme, or are locally developed. The authority attribute for a locally-developed
+ // scheme should be defined as "local". If no list or scheme controls the terms used,
+ // omit the authority attribute.
+ $this->addProperty('subject/[@authority]', METADATA_PROPERTY_TYPE_STRING, true, METADATA_PROPERTY_CARDINALITY_ONE, null, null, true);
+
+ $topicType = array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods34-subject-topic');
+ $geographicType = array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods34-subject-geographic');
+ $temporalType = array(METADATA_PROPERTY_TYPE_VOCABULARY => 'mods34-subject-temporal');
+ } else {
+ $topicType = $geographicType = $temporalType = METADATA_PROPERTY_TYPE_STRING;
+ }
+
+ // Use this subelement to indicate any primary topical subjects that are not appropriate in
+ // the geographic, temporal, or name subelements. While it is highly recommended that subject
+ // values be parsed into subelements, they may also be listed as a string under topic.
+ $this->addProperty('subject/topic', $topicType, true, METADATA_PROPERTY_CARDINALITY_MANY);
+
+ // Use this subelement for geographic subject terms. If the geographic name is part of a
+ // corporate body (for example, United States. Senate), it is coded as name, not geographic
+ $this->addProperty('subject/geographic', $geographicType, true);
+
+ // Use this subelement for chronological subject terms or temporal coverage.
+ // The first version is expressed as a subject term (historical coverage)
+ $this->addProperty('subject/temporal', $temporalType, true);
+ // The second version is expressed as a structured date using the same data
+ // definition as MODS dates.
+ $this->addProperty('subject/temporal[@encoding="w3cdtf"]', METADATA_PROPERTY_TYPE_DATE);
+ $this->addProperty('subject/temporal[@encoding="w3cdtf" @point="start"]', METADATA_PROPERTY_TYPE_DATE);
+ $this->addProperty('subject/temporal[@encoding="w3cdtf" @point="end"]', METADATA_PROPERTY_TYPE_DATE);
+
+
+ //
+ // identifier
+ //
+
+ // Unique standard numbers or codes that distinctively identify a resource.
+ $this->addProperty('identifier[@type="isbn"]');
+ $this->addProperty('identifier[@type="doi"]');
+ $this->addProperty('identifier[@type="uri"]', METADATA_PROPERTY_TYPE_URI);
+
+
+ //
+ // location
+ //
+
+ // "location" identifies the institution or repository holding the resource, or a remote
+ // location in the form of a URL where it is available.
+ $this->addProperty('location/url[@usage="primary display"]', METADATA_PROPERTY_TYPE_URI);
+
+
+ //
+ // recordInfo
+ //
+
+ // This subelement is used to record the date the original MODS record was created.
+ // Within the OAI context, service providers are more likely to rely on the
+ // datestamp within the OAI header for information about when the record was created
+ // than this date.
+ $this->addProperty('recordInfo/recordCreationDate[@encoding="w3cdtf"]', METADATA_PROPERTY_TYPE_DATE);
+
+ // Use this subelement to record the system control number assigned by the organization
+ // creating, using, or distributing the record. Within the OAI context, service providers
+ // are likely to rely on the identifier in the OAI header, rather than the recordIdentifier.
+ // If recordIdentifier is used, the guidelines recommend the use of the source attribute
+ // if possible.
+ $this->addProperty('recordInfo/recordIdentifier[@source="pkp"]');
+
+ // Use languageOfCataloging to record the language of the text of the cataloging in the
+ // MODS record. If additional language(s) are used this will be indicated with the $locale
+ // parameter within the specific element(s) in which the additional language(s)
+ // appear(s).
+ $this->addProperty('recordInfo/languageOfCataloging/languageTerm[@authority="iso639-2b"]', METADATA_PROPERTY_TYPE_STRING, false, METADATA_PROPERTY_CARDINALITY_ONE, null, null, true);
+ }
+
+
+ //
+ // Public helper methods
+ //
+ /**
+ * Translate the ISO 2-letter language string
+ * into a ISO compatible 3-letter string.
+ * @param $iso2Letter string
+ * @return string
+ */
+ function get3LetterFrom2LetterIsoLanguage($iso2Letter) {
+ $knownLanguages = $this->_getKnownLanguages();
+ if (isset($knownLanguages[$iso2Letter])) {
+ return $knownLanguages[$iso2Letter];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Translate the ISO 3-letter language string
+ * into a ISO compatible 2-letter string.
+ * @param $iso3Letter string
+ * @return string
+ */
+ function get2LetterFrom3LetterIsoLanguage($iso3Letter) {
+ $knownLanguages = $this->_getKnownLanguages(false);
+ if (isset($knownLanguages[$iso3Letter])) {
+ return $knownLanguages[$iso3Letter];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Translate the PKP locale identifier into an
+ * ISO639-2b compatible 3-letter string.
+ * @param $locale string
+ * @return string
+ */
+ function get3LetterIsoFromLocale($locale) {
+ assert(strlen($locale) == 5);
+ $iso2Letter = substr($locale, 0, 2);
+ return $this->get3LetterFrom2LetterIsoLanguage($iso2Letter);
+ }
+
+ //
+ // Private helper methods
+ //
+ /**
+ * Get a list of known languages for
+ * language symbol conversions.
+ * @param $toLong boolean true when converting from 2-letter codes
+ * to 3-letter codes, otherwise false.
+ * @return array
+ */
+ function _getKnownLanguages($toLong = true) {
+ static $knownLanguages = array(
+ 'ca' => 'cat',
+ 'cs' => 'cze',
+ 'da' => 'dan',
+ 'de' => 'ger',
+ 'el' => 'grc',
+ 'en' => 'eng',
+ 'es' => 'spa',
+ 'eu' => 'eus',
+ 'fa' => 'fas',
+ 'fr' => 'fra',
+ 'hr' => 'hrv',
+ 'it' => 'ita',
+ 'ja' => 'jpn',
+ 'nl' => 'nld',
+ 'pt' => 'por',
+ 'ro' => 'ron',
+ 'ru' => 'rus',
+ 'sv' => 'swe',
+ 'tr' => 'tur',
+ 'vi' => 'vie',
+ 'zh' => 'zho'
+ );
+
+ if ($toLong) {
+ return $knownLanguages;
+ } else {
+ return array_flip($knownLanguages);
+ }
+ }
+}
+?>
\ No newline at end of file