mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
[platform] supports 'number,ordinal' format in message bundles (IDEA-202990)
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
package com.intellij;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfoRt;
|
||||
import com.intellij.util.text.OrdinalFormat;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@@ -18,9 +20,9 @@ public abstract class BundleBase {
|
||||
|
||||
public static boolean assertKeyIsFound = false;
|
||||
|
||||
public static String messageOrDefault(@Nullable final ResourceBundle bundle,
|
||||
public static String messageOrDefault(@Nullable ResourceBundle bundle,
|
||||
@NotNull String key,
|
||||
@Nullable final String defaultValue,
|
||||
@Nullable String defaultValue,
|
||||
@NotNull Object... params) {
|
||||
if (bundle == null) return defaultValue;
|
||||
|
||||
@@ -42,7 +44,14 @@ public abstract class BundleBase {
|
||||
|
||||
value = replaceMnemonicAmpersand(value);
|
||||
|
||||
return format(value, params);
|
||||
if (params.length > 0 && value.indexOf('{') >= 0) {
|
||||
Locale locale = bundle.getLocale();
|
||||
MessageFormat format = locale != null ? new MessageFormat(value, locale) : new MessageFormat(value);
|
||||
OrdinalFormat.apply(format);
|
||||
value = format.format(params);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.text;
|
||||
|
||||
import java.text.*;
|
||||
import java.util.Locale;
|
||||
|
||||
public class OrdinalFormat {
|
||||
/**
|
||||
* Replaces all instances of {@code "{?,number,ordinal}"} format elements with the ordinal format for the locale.
|
||||
*/
|
||||
public static void apply(MessageFormat format) {
|
||||
Format[] formats = format.getFormats();
|
||||
NumberFormat ordinal = null;
|
||||
for (int i = 0; i < formats.length; i++) {
|
||||
Format element = formats[i];
|
||||
if (element instanceof DecimalFormat && "ordinal".equals(((DecimalFormat)element).getPositivePrefix())) {
|
||||
if (ordinal == null) ordinal = getOrdinalFormat(format.getLocale());
|
||||
format.setFormat(i, ordinal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static NumberFormat getOrdinalFormat(Locale locale) {
|
||||
if (locale != null) {
|
||||
String language = locale.getLanguage();
|
||||
if ("en".equals(language) ||
|
||||
language != null && language.length() == 0 /*bundle fallback locale*/) {
|
||||
return new EnglishOrdinalFormat();
|
||||
}
|
||||
}
|
||||
|
||||
return new DecimalFormat();
|
||||
}
|
||||
|
||||
private static class EnglishOrdinalFormat extends NumberFormat {
|
||||
@Override
|
||||
public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos) {
|
||||
return new MessageFormat("{0}").format(new Object[]{formatEnglish(number)}, toAppendTo, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
|
||||
throw new IllegalArgumentException("Cannot format non-integer number");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number parse(String source, ParsePosition parsePosition) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static String formatEnglish(long num) {
|
||||
long mod = Math.abs(num) % 100;
|
||||
if (mod < 11 || mod > 13) {
|
||||
mod = mod % 10;
|
||||
if (mod == 1) return num + "st";
|
||||
if (mod == 2) return num + "nd";
|
||||
if (mod == 3) return num + "rd";
|
||||
}
|
||||
return num + "th";
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,7 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.util.text.CharSequenceSubSequence;
|
||||
import com.intellij.util.text.MergingCharSequence;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import com.intellij.util.text.*;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -25,6 +22,7 @@ import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -1634,23 +1632,11 @@ public class StringUtil extends StringUtilRt {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String formatOrdinal(int i) {
|
||||
int mod = i % 100;
|
||||
if (mod == 11 || mod == 12 || mod == 13) {
|
||||
return i + "th";
|
||||
}
|
||||
|
||||
mod = mod % 10;
|
||||
if (mod == 1) {
|
||||
return i + "st";
|
||||
}
|
||||
else if (mod == 2) {
|
||||
return i + "nd";
|
||||
}
|
||||
else if (mod == 3) {
|
||||
return i + "rd";
|
||||
}
|
||||
return i + "th";
|
||||
/**
|
||||
* Appends English ordinal suffix to the given number.
|
||||
*/
|
||||
public static String formatOrdinal(long num) {
|
||||
return OrdinalFormat.formatEnglish(num);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.util.text;
|
||||
|
||||
import com.intellij.BundleBase;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class OrdinalFormatTest {
|
||||
@Test
|
||||
public void locales() {
|
||||
// the language bundle is present, but the language is not supported by the formatter - should fall back to plain decimal
|
||||
ResourceBundle fr = ResourceBundle.getBundle("com.intellij.util.text.OrdinalFormatTest$TestBundle", Locale.FRENCH);
|
||||
assertEquals("Blah blah 1 blah blah 'whatever' blah blah 33 [fr]", BundleBase.message(fr, "ordinals", 1, "whatever", 33));
|
||||
|
||||
// the language bundle isn't present - should fall back to the default (i.e. English)
|
||||
ResourceBundle de = ResourceBundle.getBundle("com.intellij.util.text.OrdinalFormatTest$TestBundle", Locale.GERMAN);
|
||||
assertEquals("Blah blah 1st blah blah 'whatever' blah blah 33rd [en]", BundleBase.message(de, "ordinals", 1, "whatever", 33));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class TestBundle extends ListResourceBundle {
|
||||
@Override
|
||||
protected Object[][] getContents() {
|
||||
return new Object[][]{{"ordinals", "Blah blah {0,number,ordinal} blah blah ''{1}'' blah blah {2,number,ordinal} [en]"}};
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class TestBundle_fr extends ListResourceBundle {
|
||||
@Override
|
||||
protected Object[][] getContents() {
|
||||
return new Object[][]{{"ordinals", "Blah blah {0,number,ordinal} blah blah ''{1}'' blah blah {2,number,ordinal} [fr]"}};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -768,4 +768,15 @@ public class StringUtilTest {
|
||||
assertTrue(String.valueOf(last.getClass()), last instanceof CharSequenceSubSequence);
|
||||
assertEquals("t", last.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnglishOrdinals() {
|
||||
assertEquals("100th", StringUtil.formatOrdinal(100));
|
||||
assertEquals("101st", StringUtil.formatOrdinal(101));
|
||||
assertEquals("111th", StringUtil.formatOrdinal(111));
|
||||
assertEquals("122nd", StringUtil.formatOrdinal(122));
|
||||
|
||||
assertEquals("-3rd", StringUtil.formatOrdinal(-3));
|
||||
assertEquals("-9223372036854775808th", StringUtil.formatOrdinal(Long.MIN_VALUE));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user