Skip to content

Commit

Permalink
Add bulgarian support (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
gavrilovniki authored Jul 22, 2022
1 parent e198506 commit 1644df5
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static pl.allegro.finance.tradukisto.internal.Container.slovakContainer;
import static pl.allegro.finance.tradukisto.internal.Container.turkishContainer;
import static pl.allegro.finance.tradukisto.internal.Container.ukrainianContainer;
import static pl.allegro.finance.tradukisto.internal.Container.bulgarianContainer;

public enum MoneyConverters {

Expand All @@ -39,7 +40,8 @@ public enum MoneyConverters {
TURKISH_BANKING_MONEY_VALUE(turkishContainer().getBankingMoneyConverter()),
SERBIAN_BANKING_MONEY_VALUE(serbianContainer().getBankingMoneyConverter()),
SERBIAN_CYRILLIC_BANKING_MONEY_VALUE(serbianCyrillicContainer().getBankingMoneyConverter()),
FRENCH_BANKING_MONEY_VALUE(frenchContainer().getBankingMoneyConverter());
FRENCH_BANKING_MONEY_VALUE(frenchContainer().getBankingMoneyConverter()),
BULGARIAN_BANKING_MONEY_VALUE(bulgarianContainer().getBankingMoneyConverter());

private final BigDecimalToStringConverter converter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import static pl.allegro.finance.tradukisto.internal.Container.slovakContainer;
import static pl.allegro.finance.tradukisto.internal.Container.turkishContainer;
import static pl.allegro.finance.tradukisto.internal.Container.ukrainianContainer;
import static pl.allegro.finance.tradukisto.internal.Container.bulgarianContainer;

public enum ValueConverters {

Expand All @@ -41,6 +42,7 @@ public enum ValueConverters {
UKRAINIAN_INTEGER(ukrainianContainer().getNumbersConverter(), "uk"),
SERBIAN_INTEGER(serbianContainer().getNumbersConverter(), Arrays.asList("sr", getLanguageCodeFor("sr", "Latn"))),
SERBIAN_CYRILLIC_INTEGER(serbianCyrillicContainer().getNumbersConverter(), getLanguageCodeFor("sr", "Cyrl")),
BULGARIAN_INTEGER(bulgarianContainer().getNumbersConverter(), "bg"),
FRENCH_INTEGER(frenchContainer().getNumbersConverter(), "fr"),
TURKISH_INTEGER(turkishContainer().getNumbersConverter(), "tr");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import pl.allegro.finance.tradukisto.internal.converters.BigDecimalToBankingMoneyConverter;
import pl.allegro.finance.tradukisto.internal.converters.HundredsToWordsConverter;
import pl.allegro.finance.tradukisto.internal.converters.IntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.bulgarian.BulgarianIntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.bulgarian.BulgarianValues;
import pl.allegro.finance.tradukisto.internal.languages.czech.CzechIntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.czech.CzechValues;
import pl.allegro.finance.tradukisto.internal.languages.czech.CzechValuesForSmallNumbers;
Expand Down Expand Up @@ -52,6 +54,24 @@ public static Container serbianCyrillicContainer() {
return new Container(new SerbianCyrillicValues());
}

public static Container bulgarianContainer() {
BulgarianValues bulgarianValues = new BulgarianValues();

HundredsToWordsConverter hundredsToStringConverter = new HundredsToWordsConverter(bulgarianValues.baseNumbers(),
bulgarianValues.twoDigitsNumberSeparator());

IntegerToStringConverter integerToStringConverter = new BulgarianIntegerToWordsConverter(
hundredsToStringConverter,
bulgarianValues.pluralForms(),
bulgarianValues.oneThousandException());

BigDecimalToStringConverter bigDecimalConverter = new BigDecimalToBankingMoneyConverter(
integerToStringConverter,
bulgarianValues.currency());

return new Container(integerToStringConverter, bigDecimalConverter);
}

public static Container ukrainianContainer() {
return new Container(new UkrainianValues());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package pl.allegro.finance.tradukisto.internal.languages.bulgarian;

import pl.allegro.finance.tradukisto.internal.converters.HundredsToWordsConverter;
import pl.allegro.finance.tradukisto.internal.converters.IntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.PluralForms;
import pl.allegro.finance.tradukisto.internal.support.NumberChunking;

import java.util.List;

import static com.google.common.collect.Lists.reverse;
import static java.lang.String.format;

public class BulgarianIntegerToWordsConverter extends IntegerToWordsConverter {

private final String oneThousand;

private static final String MERGE_PATTERN = "%s %s";
private static final int ONE_THOUSAND = 1000;
private static final int TWO_THOUSAND = 2000;

public BulgarianIntegerToWordsConverter(HundredsToWordsConverter hundredsToStringConverter, List<PluralForms> pluralForms, String oneThousand) {
super(hundredsToStringConverter, pluralForms);
this.oneThousand = oneThousand;
}

@Override
public String asWords(Integer value) {
if (value == ONE_THOUSAND) {
return oneThousand;
}

if (isBetweenOneThousandAndTwoThousand(value)) {
int remainder = getNumbersSmallerThanOneThousand(value);
return format(MERGE_PATTERN, oneThousand, super.asWords(remainder));
} else {
return super.asWords(value);
}
}

private boolean isBetweenOneThousandAndTwoThousand(Integer value) {
return value >= ONE_THOUSAND && value < TWO_THOUSAND;
}

private Integer getNumbersSmallerThanOneThousand(Integer values) {
return values % ONE_THOUSAND;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pl.allegro.finance.tradukisto.internal.languages.bulgarian;

import pl.allegro.finance.tradukisto.internal.languages.GenderType;
import pl.allegro.finance.tradukisto.internal.languages.SlavonicPluralForms;

public class BulgarianPluralForms extends SlavonicPluralForms {

private final String singularForm;

public BulgarianPluralForms(String singularForm, String pluralForm, String genitivePluralForm, GenderType genderType) {
super(singularForm, pluralForm, genitivePluralForm, genderType);
this.singularForm = singularForm;
}

@Override
public String formFor(Integer value) {
if (useSingular(value)) {
return singularForm;
} else {
return super.formFor(value);
}
}

private boolean useSingular(Integer value) {
return value == 1 || (value % 100 != 11 && value % 10 == 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package pl.allegro.finance.tradukisto.internal.languages.bulgarian;

import pl.allegro.finance.tradukisto.internal.BaseValues;
import pl.allegro.finance.tradukisto.internal.languages.GenderForms;
import pl.allegro.finance.tradukisto.internal.languages.GenderType;
import pl.allegro.finance.tradukisto.internal.languages.PluralForms;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static pl.allegro.finance.tradukisto.internal.languages.GenderForms.genderForms;
import static pl.allegro.finance.tradukisto.internal.support.BaseNumbersBuilder.baseNumbersBuilder;

public class BulgarianValues implements BaseValues {
@Override
public Map<Integer, GenderForms> baseNumbers() {
return baseNumbersBuilder()
.put(0, "нула")
.put(1, genderForms("един", "една", "едно", "един"))
.put(2, genderForms("два", "две", "две", "два"))
.put(3, "три")
.put(4, "четири")
.put(5, "пет")
.put(6, "шест")
.put(7, "седем")
.put(8, "осем")
.put(9, "девет")
.put(10, "десет")
.put(11, "единадесет")
.put(12, "дванадесет")
.put(13, "тринадесет")
.put(14, "четиринадесет")
.put(15, "петнадесет")
.put(16, "шестнадесет")
.put(17, "седемнадесет")
.put(18, "осемнадесет")
.put(19, "деветнадесет")
.put(20, "двадесет")
.put(30, "тридесет")
.put(40, "четиридесет")
.put(50, "петдесет")
.put(60, "шестдесет")
.put(70, "седемдесет")
.put(80, "осемдесет")
.put(90, "деветдесет")
.put(100, "сто")
.put(200, "двеста")
.put(300, "триста")
.put(400, "четиристотин")
.put(500, "петстотин")
.put(600, "шестстотин")
.put(700, "седемстотин")
.put(800, "осемстотин")
.put(900, "деветстотин")
.build();
}

@Override
public List<PluralForms> pluralForms() {
return Arrays.asList(
new BulgarianPluralForms("", "", "", GenderType.MASCULINE),
new BulgarianPluralForms("хиляди", "хиляди", "хиляди", GenderType.FEMININE),
new BulgarianPluralForms("милион", "милиона", "милиона", GenderType.MASCULINE),
new BulgarianPluralForms("милиард", "милиарда", "милиарда", GenderType.MASCULINE));
}

@Override
public String currency() {
return "лв";
}

@Override
public char twoDigitsNumberSeparator() {
return ' ';
}

public String oneThousandException() {
return "хиляда";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import spock.lang.Specification

import static pl.allegro.finance.tradukisto.MoneyConverters.AMERICAN_ENGLISH_BANKING_MONEY_VALUE
import static pl.allegro.finance.tradukisto.MoneyConverters.BRAZILIAN_PORTUGUESE_BANKING_MONEY_VALUE
import static pl.allegro.finance.tradukisto.MoneyConverters.BULGARIAN_BANKING_MONEY_VALUE
import static pl.allegro.finance.tradukisto.MoneyConverters.CZECH_BANKING_MONEY_VALUE
import static pl.allegro.finance.tradukisto.MoneyConverters.ENGLISH_BANKING_MONEY_VALUE
import static pl.allegro.finance.tradukisto.MoneyConverters.FRENCH_BANKING_MONEY_VALUE
Expand Down Expand Up @@ -42,6 +43,11 @@ class MoneyConvertersTest extends Specification {
RUSSIAN_BANKING_MONEY_VALUE.asWords(1_234.56) == "одна тысяча двести тридцать четыре руб. 56/100"
}

def "should convert money in Bulgarian"() {
expect:
BULGARIAN_BANKING_MONEY_VALUE.asWords(1_234.56) == "хиляда двеста тридесет четири лв 56/100"
}

def "should convert money in Polish"() {
expect:
POLISH_BANKING_MONEY_VALUE.asWords(1_234.56) == "jeden tysiąc dwieście trzydzieści cztery PLN 56/100"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class ValueConvertersTest extends Specification {
RUSSIAN_INTEGER.asWords(1_234) == "одна тысяча двести тридцать четыре"
}

def "should convert numbers in Bulgarian"() {
expect:
BULGARIAN_INTEGER.asWords(1_234) == "хиляда двеста тридесет четири"
}

def "should convert numbers in Italian"() {
expect:
ITALIAN_INTEGER.asWords(1_234) == "milleduecentotrentaquattro"
Expand Down Expand Up @@ -115,6 +120,11 @@ class ValueConvertersTest extends Specification {
getByLocaleOrDefault(new Locale("ru"), null).asWords(1_234) == "одна тысяча двести тридцать четыре"
}

def "getByLocaleOrDefault for Bulgarian"() {
expect:
getByLocaleOrDefault(new Locale("bg"), null).asWords(1_234) == "хиляда двеста тридесет четири"
}

def "getByLocaleOrDefault for Italian"() {
expect:
getByLocaleOrDefault(new Locale("it"), null).asWords(1_234) == "milleduecentotrentaquattro"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package pl.allegro.finance.tradukisto.internal.languages.bulgarian

import spock.lang.Specification
import spock.lang.Unroll

import static pl.allegro.finance.tradukisto.internal.Container.bulgarianContainer

class BulgarianValuesTest extends Specification {

static converter = bulgarianContainer().getNumbersConverter()

@Unroll
def "should convert #value to '#words' in Bulgarian"() {
expect:
converter.asWords(value) == words

where:
value | words
0 | "нула"
1 | "един"
2 | "два"
3 | "три"
4 | "четири"
5 | "пет"
6 | "шест"
7 | "седем"
8 | "осем"
9 | "девет"

11 | "единадесет"
12 | "дванадесет"
13 | "тринадесет"
14 | "четиринадесет"
15 | "петнадесет"
16 | "шестнадесет"
17 | "седемнадесет"
18 | "осемнадесет"
19 | "деветнадесет"

10 | "десет"
20 | "двадесет"
30 | "тридесет"
40 | "четиридесет"
50 | "петдесет"
60 | "шестдесет"
70 | "седемдесет"
80 | "осемдесет"
90 | "деветдесет"

21 | "двадесет един"
37 | "тридесет седем"
43 | "четиридесет три"
58 | "петдесет осем"
69 | "шестдесет девет"
76 | "седемдесет шест"
82 | "осемдесет два"
95 | "деветдесет пет"

100 | "сто"
200 | "двеста"
300 | "триста"
400 | "четиристотин"
500 | "петстотин"
600 | "шестстотин"
700 | "седемстотин"
800 | "осемстотин"
900 | "деветстотин"

111 | "сто единадесет"
272 | "двеста седемдесет два"
387 | "триста осемдесет седем"
448 | "четиристотин четиридесет осем"
569 | "петстотин шестдесет девет"
625 | "шестстотин двадесет пет"
782 | "седемстотин осемдесет два"
895 | "осемстотин деветдесет пет"
999 | "деветстотин деветдесет девет"

1_000 | "хиляда"
2_000 | "две хиляди"
3_000 | "три хиляди"
4_000 | "четири хиляди"
5_000 | "пет хиляди"
7_634 | "седем хиляди шестстотин тридесет четири"
11_000 | "единадесет хиляди"
15_000 | "петнадесет хиляди"
21_000 | "двадесет една хиляди"
24_190 | "двадесет четири хиляди сто деветдесет"
653_000 | "шестстотин петдесет три хиляди"
123_454 | "сто двадесет три хиляди четиристотин петдесет четири"
700_000 | "седемстотин хиляди"
999_999 | "деветстотин деветдесет девет хиляди деветстотин деветдесет девет"

1_000_000 | "един милион"
2_000_000 | "два милиона"
5_000_000 | "пет милиона"
23_437_219 | "двадесет три милиона четиристотин тридесет седем хиляди двеста деветнадесет"
100_000_000 | "сто милиона"
123_456_789 | "сто двадесет три милиона четиристотин петдесет шест хиляди седемстотин осемдесет девет"
322_089_890 | "триста двадесет два милиона осемдесет девет хиляди осемстотин деветдесет"

1_000_000_000 | "един милиард"
2_147_483_647 | "два милиарда сто четиридесет седем милиона четиристотин осемдесет три хиляди шестстотин четиридесет седем"
}

}

0 comments on commit 1644df5

Please sign in to comment.