Azerbaijani azərbaycan

BCP 47 language tag: az

Lokalized supports cardinality, cardinality range, and ordinality rules for Azerbaijani.

Azerbaijani is most often spoken in Azerbaijan and Türkiye.

Cardinalities

  • CARDINALITY_ONE

    Matches n = 1

    Example Integers: 1

    Example Decimals: 1.0, 1.00, 1.000, 1.0000

  • CARDINALITY_OTHER

    Matches all other values

    Example Integers: 0, 2, 16, 100, 1000, 10000, 100000, 1000000, …

    Example Decimals: 0.0, 0.9, 1.1, 1.6, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, …

Cardinality example

This localized strings example uses complete, page-local CLDR minimal-pair patterns to demonstrate every cardinality category defined for the locale. Minimal-pair text contrasts grammatical forms; it is language-reference data, not reusable application copy.

Source: Unicode CLDR 48.2 az locale data.

Sample localized strings file
az.json Localized Strings File (Azerbaijani)
{
  "Cardinality.MinimalPair": {
    "commentary": "Demonstrates every CLDR cardinal category defined for this locale.",
    "translation": "{{cardinalityExample}}",
    "placeholders": {
      "cardinalityExample": {
        "value": "cardinalityValue",
        "translations": {
          "CARDINALITY_ONE": "Alış-veriş kartınızda {{formattedCardinalityValue}} var. Alınsın?",
          "CARDINALITY_OTHER": "Alış-veriş kartınızda {{formattedCardinalityValue}} var. Alınsınlar?"
        }
      }
    }
  }
}
Usage and expected results

JavaScript

The JavaScript code passes each raw number for cardinality selection and formats its display value separately with Intl.NumberFormat.

import { cardinalityForNumber, createStrings } from "lokalized";
import { readStringsFromDirectory } from "lokalized/node";

const locale = "az";

const strings = createStrings({
  localizedStringSupplier: () => readStringsFromDirectory("strings").catalogs,
  fallbackLocale: locale,
  localeSupplier: () => locale,
});

const numberFormat = new Intl.NumberFormat(locale);

// Raw numbers select language forms; Intl.NumberFormat produces the display values

// CARDINALITY_ONE
const oneCardinality = 1;
const oneFormattedCardinalityValue = numberFormat.format(oneCardinality);

cardinalityForNumber(oneCardinality, locale).name;   // => "CARDINALITY_ONE"
strings.get("Cardinality.MinimalPair", {
  cardinalityValue: oneCardinality,
  formattedCardinalityValue: oneFormattedCardinalityValue,
});   // => "Alış-veriş kartınızda 1 var. Alınsın?"

// CARDINALITY_OTHER
const otherCardinality = 0;
const otherFormattedCardinalityValue = numberFormat.format(otherCardinality);

cardinalityForNumber(otherCardinality, locale).name;   // => "CARDINALITY_OTHER"
strings.get("Cardinality.MinimalPair", {
  cardinalityValue: otherCardinality,
  formattedCardinalityValue: otherFormattedCardinalityValue,
});   // => "Alış-veriş kartınızda 0 var. Alınsınlar?"

Java

The Java code passes each raw number for cardinality selection and formats its display value separately with NumberFormat.

Locale locale = Locale.forLanguageTag("az");

Strings strings = Strings.withFallbackLocale(locale)
  .localizedStringSupplier(() -> LocalizedStringLoader.loadFromFilesystem(Paths.get("strings")))
  .localeSupplier((matcher) -> matcher.bestMatchFor(locale))
  .build();

NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);

// Raw numbers select language forms; NumberFormat produces the display values

// CARDINALITY_ONE
Number oneCardinality = 1;
String oneFormattedCardinalityValue = numberFormat.format(oneCardinality);

assertEquals(Cardinality.ONE, Cardinality.forNumber(oneCardinality, locale));

// Expected: Alış-veriş kartınızda 1 var. Alınsın?
assertEquals("Alış-veriş kartınızda " + oneFormattedCardinalityValue + " var. Alınsın?", strings.get(
  "Cardinality.MinimalPair",
  Map.of("cardinalityValue", oneCardinality, "formattedCardinalityValue", oneFormattedCardinalityValue)
));

// CARDINALITY_OTHER
Number otherCardinality = 0;
String otherFormattedCardinalityValue = numberFormat.format(otherCardinality);

assertEquals(Cardinality.OTHER, Cardinality.forNumber(otherCardinality, locale));

// Expected: Alış-veriş kartınızda 0 var. Alınsınlar?
assertEquals(
  "Alış-veriş kartınızda " + otherFormattedCardinalityValue + " var. Alınsınlar?",
  strings.get(
    "Cardinality.MinimalPair",
    Map.of(
      "cardinalityValue", otherCardinality,
      "formattedCardinalityValue", otherFormattedCardinalityValue
    )
  )
);

Swift

Swift uses pinned CLDR rules for raw numeric values. The display strings in these assertions are fixed examples; applications format display values separately with Foundation. Default .rtlLocales bidi isolation adds FSI/PDI to interpolated values in right-to-left output.

import Foundation
import Lokalized

let locale = try LocaleTag("az")
let files = try LocalizedStringLoader.loadFromDirectory(URL(fileURLWithPath: "strings"))
let catalogs = files.mapValues { LocalizedCatalog(strings: $0.strings) }

let strings = try DefaultStrings(configuration: StringsConfiguration(
  localizedStringSupplier: { catalogs }, localeSupplier: { _ in locale },
  fallbackLocale: locale
))

// CARDINALITY_ONE
let number1 = try NumericValue.forDecimal("1")
let category1 = try Cardinality.forNumber(number1, locale: locale.tag)
assert(category1 == .one)
// This fixed display value makes the translation assertion reproducible.
let display1 = "1"
let message1 = try strings.get("Cardinality.MinimalPair", placeholders: [
  "cardinalityValue": .number(number1),
  "formattedCardinalityValue": .text(display1),
])
assert(ExactString(message1) == ExactString("Alış-veriş kartınızda 1 var. Alınsın?"))

// CARDINALITY_OTHER
let number2 = try NumericValue.forDecimal("0")
let category2 = try Cardinality.forNumber(number2, locale: locale.tag)
assert(category2 == .other)
// This fixed display value makes the translation assertion reproducible.
let display2 = "0"
let message2 = try strings.get("Cardinality.MinimalPair", placeholders: [
  "cardinalityValue": .number(number2),
  "formattedCardinalityValue": .text(display2),
])
assert(ExactString(message2) == ExactString("Alış-veriş kartınızda 0 var. Alınsınlar?"))

Cardinality Ranges

These are CLDR's explicit range mappings. For any start/end pair not listed, the range falls back to the ending cardinality.

  • CARDINALITY_ONE - CARDINALITY_OTHER

    Matches CARDINALITY_OTHER

  • CARDINALITY_OTHER - CARDINALITY_ONE

    Matches CARDINALITY_ONE

  • CARDINALITY_OTHER - CARDINALITY_OTHER

    Matches CARDINALITY_OTHER

Ordinalities

  • ORDINALITY_ONE

    Matches i % 10 = 1,2,5,7,8 or i % 100 = 20,50,70,80

    Example Integers: 1, 2, 5, 7, 8, 11, 12, 15, 17, 18, 20, 22, 25, 101, 1001, …

  • ORDINALITY_FEW

    Matches i % 10 = 3,4 or i % 1000 = 100,200,300,400,500,600,700,800,900

    Example Integers: 3, 4, 13, 14, 23, 24, 33, 34, 43, 44, 53, 54, 63, 64, 73, 74, 100, 1003, …

  • ORDINALITY_MANY

    Matches i = 0 or i % 10 = 6 or i % 100 = 40,60,90

    Example Integers: 0, 6, 16, 26, 36, 40, 46, 56, 106, 1006, …

  • ORDINALITY_OTHER

    Matches all other values

    Example Integers: 9, 10, 19, 29, 30, 39, 49, 59, 69, 79, 109, 1000, 10000, 100000, 1000000, …

Ordinality example

This localized strings example uses complete CLDR minimal-pair patterns to demonstrate every ordinality category defined for the locale.

Source: Unicode CLDR 48.2 az locale data.

Sample localized strings file
az.json Localized Strings File (Azerbaijani)
{
  "Ordinal.MinimalPair": {
    "commentary": "Demonstrates every CLDR ordinal category defined for this locale.",
    "translation": "{{ordinalExample}}",
    "placeholders": {
      "ordinalExample": {
        "value": "ordinalValue",
        "translations": {
          "ORDINALITY_ONE": "{{formattedOrdinalValue}}-ci sağ döngəni seçin.",
          "ORDINALITY_FEW": "{{formattedOrdinalValue}}-cü sağ döngəni seçin.",
          "ORDINALITY_MANY": "{{formattedOrdinalValue}}-cı sağ döngəni seçin.",
          "ORDINALITY_OTHER": "{{formattedOrdinalValue}}-cu sağ döngəni seçin."
        }
      }
    }
  }
}
Usage and expected results

JavaScript

The JavaScript code passes each raw number to ordinalityForNumber(...) and formats its display value separately with Intl.NumberFormat. Ordinal rules are an optional import, lokalized/data/ordinal.

import { createStrings } from "lokalized";
import { ordinalData, ordinalityForNumber } from "lokalized/data/ordinal";
import { readStringsFromDirectory } from "lokalized/node";

const locale = "az";

const strings = createStrings({
  localizedStringSupplier: () => readStringsFromDirectory("strings").catalogs,
  fallbackLocale: locale,
  localeSupplier: () => locale,
  pluralData: { ordinal: ordinalData },
});

const numberFormat = new Intl.NumberFormat(locale);

// Raw numbers select language forms; Intl.NumberFormat produces the display values

// ORDINALITY_ONE
const oneOrdinalValue = 1;
const oneFormattedOrdinalValue = numberFormat.format(oneOrdinalValue);

ordinalityForNumber(oneOrdinalValue, locale).name;   // => "ORDINALITY_ONE"
strings.get("Ordinal.MinimalPair", {
  ordinalValue: oneOrdinalValue,
  formattedOrdinalValue: oneFormattedOrdinalValue,
});   // => "1-ci sağ döngəni seçin."

// ORDINALITY_FEW
const fewOrdinalValue = 3;
const fewFormattedOrdinalValue = numberFormat.format(fewOrdinalValue);

ordinalityForNumber(fewOrdinalValue, locale).name;   // => "ORDINALITY_FEW"
strings.get("Ordinal.MinimalPair", {
  ordinalValue: fewOrdinalValue,
  formattedOrdinalValue: fewFormattedOrdinalValue,
});   // => "3-cü sağ döngəni seçin."

// ORDINALITY_MANY
const manyOrdinalValue = 6;
const manyFormattedOrdinalValue = numberFormat.format(manyOrdinalValue);

ordinalityForNumber(manyOrdinalValue, locale).name;   // => "ORDINALITY_MANY"
strings.get("Ordinal.MinimalPair", {
  ordinalValue: manyOrdinalValue,
  formattedOrdinalValue: manyFormattedOrdinalValue,
});   // => "6-cı sağ döngəni seçin."

// ORDINALITY_OTHER
const otherOrdinalValue = 9;
const otherFormattedOrdinalValue = numberFormat.format(otherOrdinalValue);

ordinalityForNumber(otherOrdinalValue, locale).name;   // => "ORDINALITY_OTHER"
strings.get("Ordinal.MinimalPair", {
  ordinalValue: otherOrdinalValue,
  formattedOrdinalValue: otherFormattedOrdinalValue,
});   // => "9-cu sağ döngəni seçin."

Java

The Java code passes each raw number to Ordinality.forNumber(...) and formats its display value separately with NumberFormat.

Locale locale = Locale.forLanguageTag("az");

Strings strings = Strings.withFallbackLocale(locale)
  .localizedStringSupplier(() -> LocalizedStringLoader.loadFromFilesystem(Paths.get("strings")))
  .localeSupplier((matcher) -> matcher.bestMatchFor(locale))
  .build();

NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);

// Raw numbers select language forms; NumberFormat produces the display values

// ORDINALITY_ONE
Number oneOrdinalValue = 1;
String oneFormattedOrdinalValue = numberFormat.format(oneOrdinalValue);

assertEquals(Ordinality.ONE, Ordinality.forNumber(oneOrdinalValue, locale));

// Expected: 1-ci sağ döngəni seçin.
assertEquals(oneFormattedOrdinalValue + "-ci sağ döngəni seçin.", strings.get(
  "Ordinal.MinimalPair",
  Map.of("ordinalValue", oneOrdinalValue, "formattedOrdinalValue", oneFormattedOrdinalValue)
));

// ORDINALITY_FEW
Number fewOrdinalValue = 3;
String fewFormattedOrdinalValue = numberFormat.format(fewOrdinalValue);

assertEquals(Ordinality.FEW, Ordinality.forNumber(fewOrdinalValue, locale));

// Expected: 3-cü sağ döngəni seçin.
assertEquals(fewFormattedOrdinalValue + "-cü sağ döngəni seçin.", strings.get(
  "Ordinal.MinimalPair",
  Map.of("ordinalValue", fewOrdinalValue, "formattedOrdinalValue", fewFormattedOrdinalValue)
));

// ORDINALITY_MANY
Number manyOrdinalValue = 6;
String manyFormattedOrdinalValue = numberFormat.format(manyOrdinalValue);

assertEquals(Ordinality.MANY, Ordinality.forNumber(manyOrdinalValue, locale));

// Expected: 6-cı sağ döngəni seçin.
assertEquals(manyFormattedOrdinalValue + "-cı sağ döngəni seçin.", strings.get(
  "Ordinal.MinimalPair",
  Map.of("ordinalValue", manyOrdinalValue, "formattedOrdinalValue", manyFormattedOrdinalValue)
));

// ORDINALITY_OTHER
Number otherOrdinalValue = 9;
String otherFormattedOrdinalValue = numberFormat.format(otherOrdinalValue);

assertEquals(Ordinality.OTHER, Ordinality.forNumber(otherOrdinalValue, locale));

// Expected: 9-cu sağ döngəni seçin.
assertEquals(otherFormattedOrdinalValue + "-cu sağ döngəni seçin.", strings.get(
  "Ordinal.MinimalPair",
  Map.of("ordinalValue", otherOrdinalValue, "formattedOrdinalValue", otherFormattedOrdinalValue)
));

Swift

Swift uses pinned CLDR rules for raw numeric values. The display strings in these assertions are fixed examples; applications format display values separately with Foundation. Default .rtlLocales bidi isolation adds FSI/PDI to interpolated values in right-to-left output.

import Foundation
import Lokalized

let locale = try LocaleTag("az")
let files = try LocalizedStringLoader.loadFromDirectory(URL(fileURLWithPath: "strings"))
let catalogs = files.mapValues { LocalizedCatalog(strings: $0.strings) }

let strings = try DefaultStrings(configuration: StringsConfiguration(
  localizedStringSupplier: { catalogs }, localeSupplier: { _ in locale },
  fallbackLocale: locale
))

let number1 = try NumericValue.forDecimal("1")
let category1 = try Ordinality.forNumber(number1, locale: locale.tag)
assert(category1 == .one)
let message1 = try strings.get("Ordinal.MinimalPair", placeholders: [
  "ordinalValue": .number(number1),
  "formattedOrdinalValue": .text("1"),
])
assert(ExactString(message1) == ExactString("1-ci sağ döngəni seçin."))

let number2 = try NumericValue.forDecimal("3")
let category2 = try Ordinality.forNumber(number2, locale: locale.tag)
assert(category2 == .few)
let message2 = try strings.get("Ordinal.MinimalPair", placeholders: [
  "ordinalValue": .number(number2),
  "formattedOrdinalValue": .text("3"),
])
assert(ExactString(message2) == ExactString("3-cü sağ döngəni seçin."))

let number3 = try NumericValue.forDecimal("6")
let category3 = try Ordinality.forNumber(number3, locale: locale.tag)
assert(category3 == .many)
let message3 = try strings.get("Ordinal.MinimalPair", placeholders: [
  "ordinalValue": .number(number3),
  "formattedOrdinalValue": .text("6"),
])
assert(ExactString(message3) == ExactString("6-cı sağ döngəni seçin."))

let number4 = try NumericValue.forDecimal("9")
let category4 = try Ordinality.forNumber(number4, locale: locale.tag)
assert(category4 == .other)
let message4 = try strings.get("Ordinal.MinimalPair", placeholders: [
  "ordinalValue": .number(number4),
  "formattedOrdinalValue": .text("9"),
])
assert(ExactString(message4) == ExactString("9-cu sağ döngəni seçin."))

Addendum: Language Form Rules

The language form expressions above are specified by Unicode Technical Standard #35 and use the following notation:

  • n absolute value of the source number (integer and decimals)
  • i integer digits of n
  • v number of visible fraction digits in n, with trailing zeros
  • w number of visible fraction digits in n, without trailing zeros
  • f visible fractional digits in n, with trailing zeros
  • t visible fractional digits in n, without trailing zeros
  • c/e compact decimal exponent operands used by some CLDR compact-number rules