在 Java Servlet 中自动为用户选择国家和语言

发布于 2024-11-06 23:25:47 字数 87 浏览 4 评论 0原文

我必须使用请求详细信息(IP 地址、浏览器信息等)在 Java Servlet 中自动检测用户国家/地区和语言。是否可以为大多数用户(~90%)检测到这些设置?

I have to detect user country and language automatically in Java Servlet using request details (IP address, browser information etc.). Is it possible to detect these settings for the most of users (~90%)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

隐诗 2024-11-13 23:25:47

检测语言

检测正确的语言很容易。 Web 浏览器倾向于发送 AcceptLanguage 标头,而 Java Servlet API 非常好,可以将其内容实际转换为 Locale 对象。您所要做的只是访问此信息并实施后备机制。为此,您实际上需要应用程序将支持的区域设置列表(您可以考虑创建某种属性文件,其中包含支持的区域设置和默认区域设置)。下面的示例显示了这样的实现:

public class LousyServlet extends HttpServlet {
    private Properties supportedLanguages;
    private Locale requestLocale = (Locale) supportedLanguages.get("DEFAULT");

    public LousyServlet() {
        supportedLanguages = new Properties();
        // Just for demonstration of the concept
        // you would probably load it from i.e. XML
        supportedLanguages.put("DEFAULT", Locale.US);
        // example mapping of "de" to "de_DE"
        supportedLanguages.put("de-DEFAULT", Locale.GERMANY);
        supportedLanguages.put("de_AT", new Locale("de", "AT"));
        supportedLanguages.put("de_CH", new Locale("de", "CH"));
        supportedLanguages.put("ja_JP", Locale.JAPAN);
    }

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        detectLocale(request);

        super.doGet(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        detectLocale(request);

        super.doPost(request, response);
    }

    private void detectLocale(HttpServletRequest request) {
        Enumeration locales = request.getLocales();
        while (locales.hasMoreElements()) {
            Locale locale = (Locale) locales.nextElement();
            if (supportedLanguages.contains(locale)) {
                requestLocale = locale;
                break;
            }
        }
    }

    public String getLanguage() {
        // get English name of the language
        // For native call requestLocale.getDisplayName(requestLocale)
        return requestLocale.getDisplayLanguage();
    }
}

请注意,您需要列出给定语言的所有国家/地区,因为在这种情况下它不会回退。就是因为这个原因。无论哪种方式,本地用户都倾向于使用非特定区域设置(例如,我的网络浏览器按顺序发送 pl_PL、pl、en_US、en)。原因是,有些语言根据国家/地区的不同而存在很大差异,例如巴西葡萄牙语与葡萄牙语不同,繁体中文(台湾、香港)与简体中文(中国、新加坡)不同,因此不会适当地退回到其中之一。

检测国家/地区

根据您需要此信息的目的,它可能很简单,也可能不那么简单。如果最终用户的网络浏览器配置正确,它将提示您最终用户的首选位置 - 这将是区域设置的一部分。如果您只需要该信息来决定加载哪个本地化页面,那么这可能是最好的选择。当然,如果 Locale 对象不特定(无国家/地区),您可能需要为每个受支持的非特定区域设置分配“默认”国家/地区。在这两种情况下,您都应该为最终用户提供一些切换国家/地区的方法(即通过“其他国家/地区”组合框)。该列表可以这样获取:

public String[] getOtherCountries() {
    Set<String> countries = new HashSet<String>();
    Set<Object> keys = supportedLanguages.keySet();
    for (Object key : keys) {
        Locale other = (Locale) supportedLanguages.get(key);
        if (other != requestLocale) {
            countries.add(other.getDisplayCountry(requestLocale));
        }
    }

    return countries.toArray(new String[0]);
}

但是,如果您需要它来根据位置限制对内容的访问,那么问题就更困难了。您可能会考虑检查IP。您需要准备一些包含属于给定国家/地区的地址类别的数据库。这些数据可以在互联网上找到。该解决方案的唯一问题是,用户可能会配置网络代理并在其真实位置上欺骗您的网站。此外,企业用户可能看起来像是从美国连接,而实际上他们是从英国或爱尔兰连接。不管怎样,这都是你最好的选择。

之前有一些关于GeoLocation的问题,我相信你可能会觉得它很有用。 你在这里

Detecting the language

Detecting the correct language is easy. Web browsers tend to send AcceptLanguage header and Java Servlet API is so nice to actually convert it contents to Locale object(s). All you would have to do, is just access this information and implement fall-back mechanism. To do that you actually need a list of Locales your application is going to support (you could think of creating some sort of Properties file that would contain supported locales along with default one). Example below shows such implementation:

public class LousyServlet extends HttpServlet {
    private Properties supportedLanguages;
    private Locale requestLocale = (Locale) supportedLanguages.get("DEFAULT");

    public LousyServlet() {
        supportedLanguages = new Properties();
        // Just for demonstration of the concept
        // you would probably load it from i.e. XML
        supportedLanguages.put("DEFAULT", Locale.US);
        // example mapping of "de" to "de_DE"
        supportedLanguages.put("de-DEFAULT", Locale.GERMANY);
        supportedLanguages.put("de_AT", new Locale("de", "AT"));
        supportedLanguages.put("de_CH", new Locale("de", "CH"));
        supportedLanguages.put("ja_JP", Locale.JAPAN);
    }

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        detectLocale(request);

        super.doGet(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        detectLocale(request);

        super.doPost(request, response);
    }

    private void detectLocale(HttpServletRequest request) {
        Enumeration locales = request.getLocales();
        while (locales.hasMoreElements()) {
            Locale locale = (Locale) locales.nextElement();
            if (supportedLanguages.contains(locale)) {
                requestLocale = locale;
                break;
            }
        }
    }

    public String getLanguage() {
        // get English name of the language
        // For native call requestLocale.getDisplayName(requestLocale)
        return requestLocale.getDisplayLanguage();
    }
}

Mind you, that you would need to list all the countries for given language, as it won't fall back in this case. That is for the reason. Local users tend to have non-specific Locale either way (for example my web browser sends pl_PL, pl, en_US, en in that order). And the reason is, there are some languages that differs substantially depending on the country, for example Brazilian Portuguese is different than Portuguese and Chinese Traditional (Taiwan, Hong Kong) is different than Chinese Simplified (China, Singapore) and it won't be appropriate to fall back to one of them.

Detecting country

Depending on what you need this information for, it might or might not be straightforward. If end user's web browser is configured correctly, it will give you the hint of end user's preferred location - that would be the part of Locale. If you only need that information to decide on which localized page to load, that would be probably the best option. Of course if Locale object is not specific (country-less) you may want to assign "default" country for each supported non-specific Locale. In both cases, you should provide end user with some means of switching country (i.e. through "Other countries" combo box). The list could be obtained like this:

public String[] getOtherCountries() {
    Set<String> countries = new HashSet<String>();
    Set<Object> keys = supportedLanguages.keySet();
    for (Object key : keys) {
        Locale other = (Locale) supportedLanguages.get(key);
        if (other != requestLocale) {
            countries.add(other.getDisplayCountry(requestLocale));
        }
    }

    return countries.toArray(new String[0]);
}

If however, you need this to restrict the access to the contents based on location, the problem is harder. You may think of checking the IP. You would need to prepare some Database with address classes that belongs to given country. This data could be found on the Internet. The only problem with that solution is, user may configure a web proxy and fool your web site on his real location. Also, corporate users might appear as if they connect from USA where in fact they connect from UK or Ireland. Either way, it is your best shot.

There was some question on GeoLocation before and I believe you may find it useful. Here you are.

紫南 2024-11-13 23:25:47

使用请求对象中的 getlocale。

use getlocale from request object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文