改造2:默认接受语言

ole*_*ikd 5 android retrofit2

有没有办法Accept-Language根据操作系统设置自动添加标头?

例如:我有英语(美国)作为我的系统lang,Accept-Language: en-us以一些简单的方式添加会很棒...

此外,Android N允许在设置中选择多个区域设置,因此使用它会很好:Accept-Language: da, en-gb;q=0.8, en;q=0.7

谢谢.

ole*_*ikd 8

对于任何想知道我最终得到这个的人Interceptor:

package common.network;

import java.io.IOException;
import java.util.Locale;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Created by oleynikd on 6/9/16.
 */
public class AcceptLanguageHeaderInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        Request requestWithHeaders = originalRequest.newBuilder()
                .header("Accept-Language", localeToBcp47Language(Locale.getDefault()))
                .build();
        return chain.proceed(requestWithHeaders);
    }

    /*
     * From https://github.com/apache/cordova-plugin-globalization/blob/master/src/android/Globalization.java#L140
     * @Description: Returns a well-formed ITEF BCP 47 language tag representing
     * the locale identifier for the client's current locale
     *
     * @Return: String: The BCP 47 language tag for the current locale
     */
    private static String localeToBcp47Language(Locale loc) {
        final char SEP = '-';       // we will use a dash as per BCP 47
        String language = loc.getLanguage();
        String region = loc.getCountry();
        String variant = loc.getVariant();

        // special case for Norwegian Nynorsk since "NY" cannot be a variant as per BCP 47
        // this goes before the string matching since "NY" wont pass the variant checks
        if( language.equals("no") && region.equals("NO") && variant.equals("NY")){
            language = "nn";
            region = "NO";
            variant = "";
        }

        if( language.isEmpty() || !language.matches("\\p{Alpha}{2,8}")){
            language = "und";       // Follow the Locale#toLanguageTag() implementation
            // which says to return "und" for Undetermined
        }else if(language.equals("iw")){
            language = "he";        // correct deprecated "Hebrew"
        }else if(language.equals("in")){
            language = "id";        // correct deprecated "Indonesian"
        }else if(language.equals("ji")){
            language = "yi";        // correct deprecated "Yiddish"
        }

        // ensure valid country code, if not well formed, it's omitted
        if (!region.matches("\\p{Alpha}{2}|\\p{Digit}{3}")) {
            region = "";
        }

        // variant subtags that begin with a letter must be at least 5 characters long
        if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}")) {
            variant = "";
        }

        StringBuilder bcp47Tag = new StringBuilder(language);
        if (!region.isEmpty()) {
            bcp47Tag.append(SEP).append(region);
        }
        if (!variant.isEmpty()) {
            bcp47Tag.append(SEP).append(variant);
        }

        return bcp47Tag.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你就可以使用它:

private static final OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(new AcceptLanguageHeaderInterceptor())
            .build();
Run Code Online (Sandbox Code Playgroud)


Dmy*_*lyk 7

如果您使用 API 21,则可以使用Locale.toLanguageTag()

toLanguageTag
Added in API level 21
String toLanguageTag ()
Returns a well-formed IETF BCP 47 language tag representing this locale.
Run Code Online (Sandbox Code Playgroud)

示例代码:

private class AcceptLanguageInterceptor(val locale: Locale) : Interceptor {

        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): okhttp3.Response = chain.proceed(chain.request().newBuilder()
                .header("Accept-Language", locale.toLanguageTag())
                .build())
}
Run Code Online (Sandbox Code Playgroud)


use*_*644 7

如果有人在寻找一种解决方案,该方法如何提供首选语言列表作为接受语言,则在Android中,这是一种解决方法。注意:设置首选语言列表仅在API Level 24之后可用

  public class AcceptLanguageHeaderInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
      Request originalRequest = chain.request();
      Request requestWithHeaders = originalRequest.newBuilder()
        .header("Accept-Language", getLanguage())
        .build();
      return chain.proceed(requestWithHeaders);
    }

    private String getLanguage() {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return LocaleList.getDefault().toLanguageTags();
      } else {
        return Locale.getDefault().getLanguage();
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)


E-K*_*ami 5

创建Retrofit对象时,您可以自定义OkHttp网络库发送的标头。考虑下面的例子:

Retrofit ret = new Retrofit.Builder()
                .client(new OkHttpClient.Builder()
                .addNetworkInterceptor(new Interceptor() {

                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request.Builder builder = chain.request().newBuilder();

                        builder.addHeader("Accept-Language", "Your value");
                        Request request = builder.build();
                        Response response = chain.proceed(request);

                        return response;
                    }
                }).build())
                .build();
Run Code Online (Sandbox Code Playgroud)

在“您的价值”字符串中,您可以调整标题的值并输入例如: builder.addHeader("Accept-Language", Locale.getDefault().getDisplayLanguage())

  • 我知道我可以使用 `Interceptor` 来实现这个结果。我只是想有一些更简单的方法。问题不仅在于创建新的拦截器,还在于格式化语言代码,因为`Locale.getDefault().getDisplayLanguage()` 将返回一个**显示名称**,而不是符合 [BCP 47](http://www .w3.org/International/articles/language-tags/)。不过,谢谢! (2认同)

Mil*_*yas -2

如果您想查看设备的所选语言

使用此代码:

Locale.getDefault().getDisplayLanguage();
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助!干杯!