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);

(注意:从果冻豆 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 我只保留:

公共静态 CharSequence getRelativeTimeSpanString(很长时间,很长时间,很长的 minResolution,int 标志,上下文 c)

我将上下文添加到方法中,然后更改了上下文资源的系统资源和我自己的字符串的所有内部 android 字符串(与 android 的相同,但由于它们是内部的,所以找不到使用它们的方法)。

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 回答