13

次を使用して、アプリのロケールをオーバーライドします。

 Locale locale = new Locale("ca");
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config,
            getBaseContext().getResources().getDisplayMetrics());

しかし、それはgetRelativeTimeSpanStringアプリケーション コンテキストでは機能せず、代わりにシステム ロケールを使用しているようです。

4

3 に答える 3

16

あなたの解決策はほぼ正しかった。

ただし、文字列はシステム リソースから読み込まれるため、システム リソースの構成を更新する必要があります。以下は私がしたことです:

    Configuration configuration = new Configuration(Resources.getSystem().getConfiguration());
        configuration.locale = Locale.GERMANY; // or whichever locale you desire
        Resources.getSystem().updateConfiguration(configuration, null);

(注: Jelly Bean MR1 以降は、

configuration.setLocale(Locale.GERMANY);

メンバーを直接設定するのではなく、ロケールを変更します。)

于 2014-06-18T16:18:07.313 に答える
5

今日この問題が発生し、「解決」するのに数時間かかりました。

getRelativeTimeSpanString(context, long, boolean) を使用できる場合は、代わりに使用することをお勧めします。結果の文字列は getRelativeTimeSpanString(long) と同じではないため、私の場合ではありませんでした。

私の回避策では、いくつかの文字列の Android 内部リソースをコードにコピーする必要があるため、サポートする言語が多数ある場合は非常に面倒です。

Android (4.4 r1) の現在のソース コードを追跡し、DateUtils を抽出して変更したので、次のように使用できます。

CharSequence desiredString = MyDateUtils.getRelativeTimeSpanString(time, 
                System.currentTimeMillis(), 
                DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR, activity);

これにより、getRelativeTimeSpanString(long) と同じ結果が得られます。

MyDateUtils を作成するには、私は保持しただけです:

public static CharSequence getRelativeTimeSpanString(長い時間、長い現在、長い minResolution、int フラグ、Context c)

メソッドにコンテキストを追加し、システム リソースをコンテキスト リソース用に変更し、すべての内部 Android 文字列を自分の文字列用に変更しました (これは Android のものと同じですが、 internalであるため、それらを使用する方法が見つかりませんでした)。

private static final String getRelativeDayString(Resources r, long day, long today)

また、このメソッドは事前に使用されたままにしました。ここで弦も交換。

コピペ目的で

これは MyDateUtils の私の実装です:

import java.util.Locale;
import android.content.Context;
import android.content.res.Resources;
import android.text.format.DateUtils;
import android.text.format.Time;
import com.YOURPACKAGE.R;
/**
 * This class contains various date-related utilities for creating text for things like
 * elapsed time and date ranges, strings for days of the week and months, and AM/PM text     etc.
 */
public class MyDateUtils
{

/**
 * Returns a string describing 'time' as a time relative to 'now'.
 * <p>
 * Time spans in the past are formatted like "42 minutes ago". Time spans in
 * the future are formatted like "in 42 minutes".
 * <p>
 * Can use {@link #FORMAT_ABBREV_RELATIVE} flag to use abbreviated relative
 * times, like "42 mins ago".
 *
 * @param time the time to describe, in milliseconds
 * @param now the current time in milliseconds
 * @param minResolution the minimum timespan to report. For example, a time
 *            3 seconds in the past will be reported as "0 minutes ago" if
 *            this is set to MINUTE_IN_MILLIS. Pass one of 0,
 *            MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS,
 *            WEEK_IN_MILLIS
 * @param flags a bit mask of formatting options, such as
 *            {@link #FORMAT_NUMERIC_DATE} or
 *            {@link #FORMAT_ABBREV_RELATIVE}
 */
public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution,
        int flags, Context c) {
    Resources r = c.getResources();
    //boolean abbrevRelative = (flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0;

    boolean past = (now >= time);
    long duration = Math.abs(now - time);

    int resId;
    long count;
    if (duration < DateUtils.MINUTE_IN_MILLIS && minResolution < DateUtils.MINUTE_IN_MILLIS) {
        count = duration / DateUtils.SECOND_IN_MILLIS;
        if (past) {
            resId = R.plurals.num_seconds_ago;
        } else {
            resId = R.plurals.in_num_seconds;
        }
    } else if (duration < DateUtils.HOUR_IN_MILLIS && minResolution < DateUtils.HOUR_IN_MILLIS) {
        count = duration / DateUtils.MINUTE_IN_MILLIS;
        if (past) {
            resId = R.plurals.num_minutes_ago;
        } else {
            resId = R.plurals.in_num_minutes;
        }
    } else if (duration < DateUtils.DAY_IN_MILLIS && minResolution < DateUtils.DAY_IN_MILLIS) {
        count = duration / DateUtils.HOUR_IN_MILLIS;
        if (past) {
            resId = R.plurals.num_hours_ago;
        } else {
            resId = R.plurals.in_num_hours;
        }
    } else if (duration < DateUtils.WEEK_IN_MILLIS && minResolution < DateUtils.WEEK_IN_MILLIS) {
        return getRelativeDayString(r, time, now);
    } else {
        // We know that we won't be showing the time, so it is safe to pass
        // in a null context.
        return DateUtils.formatDateRange(null, time, time, flags);
    }

    String format = r.getQuantityString(resId, (int) count);
    return String.format(format, count);
}



/**
 * Returns a string describing a day relative to the current day. For example if the day is
 * today this function returns "Today", if the day was a week ago it returns "7 days ago", and
 * if the day is in 2 weeks it returns "in 14 days".
 *
 * @param r the resources
 * @param day the relative day to describe in UTC milliseconds
 * @param today the current time in UTC milliseconds
 */
private static final String getRelativeDayString(Resources r, long day, long today) {
    Locale locale = r.getConfiguration().locale;
    if (locale == null) {
        locale = Locale.getDefault();
    }

    // TODO: use TimeZone.getOffset instead.
    Time startTime = new Time();
    startTime.set(day);
    int startDay = Time.getJulianDay(day, startTime.gmtoff);

    Time currentTime = new Time();
    currentTime.set(today);
    int currentDay = Time.getJulianDay(today, currentTime.gmtoff);

    int days = Math.abs(currentDay - startDay);
    boolean past = (today > day);

    // TODO: some locales name other days too, such as de_DE's "Vorgestern" (today - 2).
    if (days == 1) {
        if (past) {
            return r.getString(R.string.yesterday);
        } else {
            return r.getString(R.string.tomorrow);
        }
    } else if (days == 0) {
        return r.getString(R.string.today);
    }

    int resId;
    if (past) {
        resId = R.plurals.num_days_ago;
    } else {
        resId = R.plurals.in_num_days;
    }

    String format = r.getQuantityString(resId, days);
    return String.format(format, days);
}
}

値フォルダー string.xml に次を追加します。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 <string name="yesterday">yesterday</string>
 <string name="tomorrow">tomorrow</string>
 <string name="today">today</string>

    <plurals name="num_seconds_ago">
        <item quantity="one">1 second ago</item>
        <item quantity="other"><xliff:g id="count">%d</xliff:g> seconds ago</item>
    </plurals>
    <plurals name="num_minutes_ago">
        <item quantity="one">1 minute ago</item>
        <item quantity="other"><xliff:g id="count">%d</xliff:g> minutes ago</item>
    </plurals>
    <plurals name="num_hours_ago">
        <item quantity="one">1 hour ago</item>
        <item quantity="other"><xliff:g id="count">%d</xliff:g> hours ago</item>
    </plurals>
    <plurals name="num_days_ago">
        <item quantity="one">yesterday</item>
        <item quantity="other"><xliff:g id="count">%d</xliff:g> days ago</item>
    </plurals>
    <plurals name="in_num_seconds">
        <item quantity="one">in 1 second</item>
        <item quantity="other">in <xliff:g id="count">%d</xliff:g> seconds</item>
    </plurals>
    <plurals name="in_num_minutes">
        <item quantity="one">in 1 minute</item>
        <item quantity="other">in <xliff:g id="count">%d</xliff:g> minutes</item>
    </plurals>
    <plurals name="in_num_hours">
        <item quantity="one">in 1 hour</item>
        <item quantity="other">in <xliff:g id="count">%d</xliff:g> hours</item>
    </plurals>
    <plurals name="in_num_days">
        <item quantity="one">tomorrow</item>
        <item quantity="other">in <xliff:g id="count">%d</xliff:g> days</item>
    </plurals>
</resources>

例として、ポルトガル語などの別の言語の場合、values-pt フォルダー string.xml で次のようにします。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">


    <string name="yesterday">ontem</string>
    <string name="tomorrow">manhã</string>
    <string name="today">hoje</string>

    <plurals name="num_seconds_ago">
        <item msgid="4869870056547896011" quantity="one">"1 segundo atrás"</item>
        <item msgid="3903706804349556379" quantity="other">"<xliff:g id="COUNT">%d</xliff:g> segundos atrás"</item>
    </plurals>
    <plurals name="num_minutes_ago">
        <item msgid="3306787433088810191" quantity="one">"1 minuto atrás"</item>
        <item msgid="2176942008915455116" quantity="other">"<xliff:g id="COUNT">%d</xliff:g> minutos atrás"</item>
    </plurals>
    <plurals name="num_hours_ago">
        <item msgid="9150797944610821849" quantity="one">"1 hora atrás"</item>
        <item msgid="2467273239587587569" quantity="other">"<xliff:g id="COUNT">%d</xliff:g> horas atrás"</item>
    </plurals>
    <plurals name="num_days_ago">
        <item msgid="861358534398115820" quantity="one">"ontem"</item>
        <item msgid="2479586466153314633" quantity="other">"<xliff:g id="COUNT">%d</xliff:g> dias atrás"</item>
    </plurals>
    <plurals name="in_num_seconds">
        <item msgid="2729745560954905102" quantity="one">"em 1 segundo"</item>
        <item msgid="1241926116443974687" quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> segundos"</item>
    </plurals>
    <plurals name="in_num_minutes">
        <item msgid="8793095251325200395" quantity="one">"em 1 minuto"</item>
        <item msgid="3330713936399448749" quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> minutos"</item>
    </plurals>
    <plurals name="in_num_hours">
        <item msgid="7164353342477769999" quantity="one">"em 1 hora"</item>
        <item msgid="547290677353727389" quantity="other">"Em <xliff:g id="COUNT">%d</xliff:g> horas"</item>
    </plurals>
    <plurals name="in_num_days">
        <item msgid="5413088743009839518" quantity="one">"amanhã"</item>
        <item msgid="5109449375100953247" quantity="other">"em <xliff:g id="COUNT">%d</xliff:g> dias"</item>
    </plurals>

</resources>
于 2014-04-23T08:46:00.403 に答える
2

私はカスタムメソッドを使用してこれを処理します:

public static String getRelativeTimeSpanString(Context context, Date fromdate) {

long then;
then = fromdate.getTime();
Date date = new Date(then);

StringBuffer dateStr = new StringBuffer();

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
Calendar now = Calendar.getInstance();

int days = daysBetween(calendar.getTime(), now.getTime());
int weeks= days/7;
int minutes = hoursBetween(calendar.getTime(), now.getTime());
int hours = minutes / 60;
if (days == 0) {

    int second = minuteBetween(calendar.getTime(), now.getTime());
    if (minutes > 60) {
        if (hours >= 1 && hours <= 24) {
            dateStr.append(String.format("%s %s %s",
                    hours,
                    context.getString(R.string.hour)
                    ,context.getString(R.string.ago)));
        }
    }else {
        if (second <= 10) {
            dateStr.append(context.getString(R.string.now));
        } else if (second > 10 && second <= 30) {
            dateStr.append(context.getString(R.string.few_seconds_ago));
        } else if (second > 30 && second <= 60) {
            dateStr.append(String.format("%s %s %s",
                    second,
                    context.getString(R.string.seconds)
                    ,context.getString(R.string.ago)));
        } else if (second >= 60 && minutes <= 60) {
            dateStr.append(String.format("%s %s %s",
                    minutes,
                    context.getString(R.string.minutes)
                    ,context.getString(R.string.ago)));
        }
    }
} else

if (hours > 24 && days < 7) {
    dateStr.append(String.format("%s %s %s",
            days,
            context.getString(R.string.days)
            ,context.getString(R.string.ago)));
}else if(weeks == 1){
    dateStr.append(String.format("%s %s %s",
            weeks,
            context.getString(R.string.weeks)
            ,context.getString(R.string.ago)));
}
else {
    /**
     * make formatted createTime by languageTag("fa")
     *
     * @return
     */
    return SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG,new Locale("fra"))
            .format(date).toUpperCase();
}

return dateStr.toString();
}

public static int minuteBetween(Date d1, Date d2) {
return (int) ((d2.getTime() - d1.getTime()) / android.text.format.DateUtils.SECOND_IN_MILLIS);
}

public static int hoursBetween(Date d1, Date d2) {
return (int) ((d2.getTime() - d1.getTime()) / android.text.format.DateUtils.MINUTE_IN_MILLIS);
}

public static int daysBetween(Date d1, Date d2) {
return (int) ((d2.getTime() - d1.getTime()) / android.text.format.DateUtils.DAY_IN_MILLIS);
}

そして、このメソッドにパラメーターとして日付を設定します。

 return getRelativeTimeSpanString(context,this.createdTime);

これは、私が望んでいた場所ごとに文字列を返します! お役に立てれば幸いです。

于 2016-05-23T13:34:05.537 に答える