Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Hebrew support - PR with code originally submitted by tnsilver (#38) #52

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Supported languages
* English
* French
* German
* Hebrew
* Italian
* Kazakh
* Latvian
Expand All @@ -47,7 +48,7 @@ repositories {
}

dependencies {
compile 'pl.allegro.finance:tradukisto:1.10.2'
compile 'pl.allegro.finance:tradukisto:1.11.0'
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import static pl.allegro.finance.tradukisto.internal.Container.englishContainer;
import static pl.allegro.finance.tradukisto.internal.Container.frenchContainer;
import static pl.allegro.finance.tradukisto.internal.Container.germanContainer;
import static pl.allegro.finance.tradukisto.internal.Container.hebrewContainer;
import static pl.allegro.finance.tradukisto.internal.Container.italianContainer;
import static pl.allegro.finance.tradukisto.internal.Container.kazakhContainer;
import static pl.allegro.finance.tradukisto.internal.Container.latvianContainer;
Expand Down Expand Up @@ -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()),
HEBREW_BANKING_MONEY_VALUE(hebrewContainer().getBankingMoneyConverter());

private final BigDecimalToStringConverter converter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static pl.allegro.finance.tradukisto.internal.Container.englishContainer;
import static pl.allegro.finance.tradukisto.internal.Container.frenchContainer;
import static pl.allegro.finance.tradukisto.internal.Container.germanContainer;
import static pl.allegro.finance.tradukisto.internal.Container.hebrewContainer;
import static pl.allegro.finance.tradukisto.internal.Container.italianContainer;
import static pl.allegro.finance.tradukisto.internal.Container.kazakhContainer;
import static pl.allegro.finance.tradukisto.internal.Container.latvianContainer;
Expand Down Expand Up @@ -42,7 +43,8 @@ public enum ValueConverters {
SERBIAN_INTEGER(serbianContainer().getNumbersConverter(), Arrays.asList("sr", getLanguageCodeFor("sr", "Latn"))),
SERBIAN_CYRILLIC_INTEGER(serbianCyrillicContainer().getNumbersConverter(), getLanguageCodeFor("sr", "Cyrl")),
FRENCH_INTEGER(frenchContainer().getNumbersConverter(), "fr"),
TURKISH_INTEGER(turkishContainer().getNumbersConverter(), "tr");
TURKISH_INTEGER(turkishContainer().getNumbersConverter(), "tr"),
HEBREW_INTEGER(hebrewContainer().getNumbersConverter(), Arrays.asList("he", "iw"));

private final IntegerToStringConverter converter;
private final List<String> languageCodes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
import pl.allegro.finance.tradukisto.internal.languages.german.GermanIntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.german.GermanThousandToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.german.GermanValues;
import pl.allegro.finance.tradukisto.internal.languages.hebrew.HebrewBigDecimalToBankingMoneyConverter;
import pl.allegro.finance.tradukisto.internal.languages.hebrew.HebrewHundredsToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.hebrew.HebrewIntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.hebrew.HebrewValues;
import pl.allegro.finance.tradukisto.internal.languages.italian.ItalianIntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.italian.ItalianThousandToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.italian.ItalianValues;
Expand Down Expand Up @@ -181,6 +185,16 @@ public static Container kazakhContainer() {
return new Container(kazakhValues);
}

public static Container hebrewContainer() {
HebrewValues conversionValues = new HebrewValues();
HebrewValues monetaryValues = new HebrewValues();
HebrewHundredsToWordsConverter hundredsConverter = new HebrewHundredsToWordsConverter(conversionValues);
HebrewIntegerToWordsConverter intConverter = new HebrewIntegerToWordsConverter(hundredsConverter, conversionValues);
HebrewIntegerToWordsConverter decimaConverter = new HebrewIntegerToWordsConverter(hundredsConverter, monetaryValues);
BigDecimalToStringConverter monetaryConverter = new HebrewBigDecimalToBankingMoneyConverter(decimaConverter, monetaryValues);
return new Container(intConverter, monetaryConverter);
}

private final IntegerToStringConverter integerConverter;
private final BigDecimalToStringConverter bigDecimalConverter;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package pl.allegro.finance.tradukisto.internal.languages.hebrew;

import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;

import java.math.BigDecimal;

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

/**
* @author <a href="mailto:[email protected]">T.N.Silverman</a>
* @version 1.11.0
* @since 1.11.0
*/
public class HebrewBigDecimalToBankingMoneyConverter implements BigDecimalToStringConverter {
private final String prefix, suffix, currency;

private final HebrewIntegerToWordsConverter converter;

public HebrewBigDecimalToBankingMoneyConverter(HebrewIntegerToWordsConverter converter, HebrewValues values) {
this.converter = converter;
values.setPluralForms(GenderType.MASCULINE);
prefix = values.decimalPrefix();
suffix = values.decimalSuffix();
currency = values.currency();
}

@Override
public String asWords(BigDecimal value) {
validate(value);
Integer units = value.intValue();
int decimal = value.remainder(BigDecimal.ONE).multiply(new BigDecimal(100)).intValue();
if (decimal <= 0) {
return format("%s %s", currency, asWord(units, GenderType.MASCULINE));
}
return format("%s %s %s%s %s", asWord(units, GenderType.MASCULINE), currency, prefix, asWord(decimal, GenderType.FEMININE), suffix);
}

private void validate(BigDecimal value) {
checkArgument(value.scale() <= 2, "can't transform more than %s decimal places for value %s", 2, value);
checkArgument(valueLessThanIntMax(value), "can't transform numbers greater than Integer.MAX_VALUE for value %s", value);
checkArgument(valueGreaterThanOrEqualToZero(value), "can't transform negative numbers for value %s", value);
}

private boolean valueLessThanIntMax(BigDecimal value) {
return value.compareTo(new BigDecimal(Integer.MAX_VALUE).add(BigDecimal.ONE)) == -1;
}

private boolean valueGreaterThanOrEqualToZero(BigDecimal value) {
return value.signum() >= 0;
}

private String asWord(Integer value, GenderType genderType) {
converter.hebrewValues().setPluralForms(genderType);
String word = converter.asWords(value);
converter.hebrewValues().setPluralForms(GenderType.FEMININE);
return word;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package pl.allegro.finance.tradukisto.internal.languages.hebrew;

import com.google.common.collect.Range;
import pl.allegro.finance.tradukisto.internal.GenderAwareIntegerToStringConverter;
import pl.allegro.finance.tradukisto.internal.languages.GenderForms;
import pl.allegro.finance.tradukisto.internal.languages.GenderType;

import java.util.Map;

import static java.lang.String.format;

/**
* @author <a href="mailto:[email protected]">T.N.Silverman</a>
* @version 1.11.0
* @since 1.11.0
*/
public class HebrewHundredsToWordsConverter implements GenderAwareIntegerToStringConverter {

private final Map<Integer, GenderForms> baseNumbers;
private final char twoDigitsNumberSeparator;
private final Integer ten = 10;
private final Integer hundred = 100;

public HebrewHundredsToWordsConverter(HebrewValues hebrewValues) {
this.baseNumbers = hebrewValues.baseNumbers();
this.twoDigitsNumberSeparator = hebrewValues.twoDigitsNumberSeparator();
}

@Override
public String asWords(Integer value, GenderType genderType) {
if (baseNumbers.containsKey(value)) {
return baseNumbers.get(value).formFor(genderType);
} else if (Range.closed(10, 99).contains(value)) {
return twoDigitsNumberAsString(value, genderType);
} else if (Range.closed(100, 999).contains(value)) {
return threeDigitsNumberAsString(value, genderType);
}
throw new IllegalArgumentException(format("Can't convert %s", value));
}

private String twoDigitsNumberAsString(Integer value, GenderType genderType) {
Integer units = value % ten;
Integer tens = value - units;
return format("%s %s%s", asWords(tens, genderType), twoDigitsNumberSeparator, asWords(units, genderType));
}

private String threeDigitsNumberAsString(Integer value, GenderType genderType) {
Integer tensWithUnits = value % hundred;
Integer hundreds = value - tensWithUnits;
if (tensWithUnits % ten == 0 || Range.closed(1, 19).contains(tensWithUnits)) {
return String
.format("%s %s%s", asWords(hundreds, genderType), twoDigitsNumberSeparator, asWords(tensWithUnits, genderType));
}
return String.format("%s %s", asWords(hundreds, genderType), asWords(tensWithUnits, genderType));
}

protected Map<Integer, GenderForms> baseNumbers() {
return baseNumbers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package pl.allegro.finance.tradukisto.internal.languages.hebrew;

import static java.lang.String.format;

import java.util.Map;

import com.google.common.collect.Range;

import pl.allegro.finance.tradukisto.internal.GenderAwareIntegerToStringConverter;
import pl.allegro.finance.tradukisto.internal.converters.IntegerToWordsConverter;
import pl.allegro.finance.tradukisto.internal.languages.GenderForms;
import pl.allegro.finance.tradukisto.internal.languages.GenderType;

/**
* @author <a href="mailto:[email protected]">T.N.Silverman</a>
* @version 1.11.0
* @since 1.11.0
*/
public class HebrewIntegerToWordsConverter extends IntegerToWordsConverter {

private final HebrewValues hebrewValues;
private final Map<Integer, String> exceptions;
private final Map<Integer, GenderForms> baseNumbers;
private final String wordForMillion, wordForThousand;
private final Integer thousand = 1000;
private final Integer million = thousand * thousand;
private final Integer billion = million * thousand;

public HebrewIntegerToWordsConverter(GenderAwareIntegerToStringConverter genderAwareintegerToStringConverter,
HebrewValues hebrewValues) {
super(genderAwareintegerToStringConverter, hebrewValues.pluralForms());
this.hebrewValues = hebrewValues;
this.exceptions = hebrewValues.exceptions();
this.baseNumbers = hebrewValues.baseNumbers();
wordForMillion = baseNumbers.get(million).formFor(GenderType.MASCULINE);
wordForThousand = baseNumbers.get(thousand).formFor(GenderType.MASCULINE);
}

@Override
public String asWords(Integer value) {
if (exceptions.containsKey(value)) {
return exceptions.get(value);
}
if (Range.closed(1000, 19999).contains(value)) {
return thousandAsString(value);
}
if (Range.closed(20000, 999999).contains(value)) {
return thousandsAsString(value);
}
if (Range.closed(1000000, 10999999).contains(value)) {
return millionAsString(value);
}
if (Range.closed(11000000, 999999999).contains(value)) {
return millionsAsString(value);
}
if (Range.closed(1000000000, Integer.MAX_VALUE).contains(value)) {
return billionsAsString(value);
}
return super.asWords(value);
}

private String thousandAsString(Integer value) {
Integer thousands = value / thousand;
Integer remain = value % thousand;
String word = baseNumbers.get(thousands * thousand).formFor(GenderType.MASCULINE);
if (nothingComesAfter(remain)) {
return word;
}
if (Range.closed(1, 19).contains(remain)) {
return format("%s %s%s", word, hebrewValues.twoDigitsNumberSeparator(), asWords(remain));
}
return format("%s %s", word, asWords(remain));
}

private String thousandsAsString(Integer value) {
Integer thousands = value / thousand;
Integer remain = value % thousand;
String word = hundredsToWordsConverter.asWords(thousands, GenderType.MASCULINE);
if (nothingComesAfter(remain)) {
return format("%s %s", word, wordForThousand);
}
if ((remain <= 100 && remain % 10 == 0) || Range.closed(1, 19).contains(remain)) {
return format("%s %s %s%s", word, wordForThousand, hebrewValues.twoDigitsNumberSeparator(), asWords(remain));
}
return format("%s %s %s", word, wordForThousand, asWords(remain));
}

private String millionAsString(Integer value) {
Integer millions = value / million;
Integer remain = value % million;
String word = baseNumbers.get(millions * million).formFor(GenderType.MASCULINE);
if (nothingComesAfter(remain)) {
return word;
}
if (remain % 100 == 0 || Range.closed(1, 19).contains(remain)) {
return format("%s %s%s", word, hebrewValues.twoDigitsNumberSeparator(), asWords(remain));
}
return format("%s %s", word, asWords(remain));
}

private String millionsAsString(Integer value) {
Integer millions = value / million;
Integer remain = value % million;
String word = hundredsToWordsConverter.asWords(millions, GenderType.MASCULINE);
if (nothingComesAfter(remain)) {
return format("%s %s", word, wordForMillion);
}
if ((remain <= 100 && remain % 10 == 0) || Range.closed(1, 19).contains(remain)) {
return format("%s %s %s%s", word, wordForMillion, hebrewValues.twoDigitsNumberSeparator(), asWords(remain));
}
return format("%s %s %s", word, wordForMillion, asWords(remain));
}

private String billionsAsString(Integer value) {
Integer billions = value / billion;
Integer remain = value % billion;
String word = baseNumbers.get(billions * billion).formFor(GenderType.MASCULINE);
if (nothingComesAfter(remain)) {
return word;
}
if (Range.closed(1, 19).contains(remain)) {
return format("%s %s%s", word, hebrewValues.twoDigitsNumberSeparator(), asWords(remain));
}
return format("%s %s", word, asWords(remain));
}

private boolean nothingComesAfter(Integer other) {
return other == 0;
}

protected HebrewValues hebrewValues() {
return hebrewValues;
}

protected HebrewHundredsToWordsConverter hundredsToWordsConverter() {
return (HebrewHundredsToWordsConverter) this.hundredsToWordsConverter;
}
}
Loading