Làm thế nào để quốc tế hóa một ứng dụng web Java?


81

Tôi học được từ Google rằng Quốc tế hóa là quá trình tôi có thể làm cho ứng dụng web của mình sử dụng tất cả các ngôn ngữ. Tôi muốn hiểu Unicode cho quá trình quốc tế hóa, vì vậy tôi đã tìm hiểu về Unicode từ đâyở đó .

Tôi có thể hiểu về Unicode rằng cách một bộ mã được mã hóa thành byte và các byte lại được giải mã thành bảng mã. Nhưng tôi không biết làm thế nào để tiến xa hơn. Tôi muốn học cách so sánh các chuỗi và tôi cần biết cách triển khai quốc tế hóa trong ứng dụng web của mình. Bất kỳ đề xuất xin vui lòng? Xin vui lòng hướng dẫn cho tôi.

Mục tiêu của tôi:

Mục tiêu chính của tôi là phát triển Ứng dụng web để dịch (từ tiếng Anh sang tiếng Ả Rập và ngược lại). Tôi muốn theo Quốc tế hóa. Tôi muốn chạy Ứng dụng web của mình để dịch trên cả ba trình duyệt là FF, Chrome, IE. Làm cách nào để đạt được điều này?

Câu trả lời:


221

Trong trường hợp ứng dụng web JSP / Servlet cơ bản, cách tiếp cận cơ bản sẽ là sử dụng JSTL fmttaglib kết hợp với các gói tài nguyên . Gói tài nguyên chứa các cặp khóa-giá trị trong đó khóa là một hằng số giống nhau cho tất cả các ngôn ngữ và giá trị khác nhau trên mỗi ngôn ngữ. Gói tài nguyên thường là các tệp thuộc tính được tải bởi ResourceBundleAPI. Tuy nhiên, điều này có thể được tùy chỉnh để bạn có thể tải các cặp khóa-giá trị từ cơ sở dữ liệu chẳng hạn.

Đây là ví dụ về cách quốc tế hóa biểu mẫu đăng nhập ứng dụng web của bạn với các gói tài nguyên dựa trên tệp thuộc tính.


  1. Tạo các tệp sau và đặt chúng trong một số gói, ví dụ com.example.i18n(trong trường hợp của Maven, hãy đặt chúng vào cấu trúc gói bên trong src/main/resources).

    text.properties (chứa các cặp khóa-giá trị bằng ngôn ngữ mặc định, thường là tiếng Anh)

     login.label.username = Tên người dùng
     login.label.password = Mật khẩu
     login.button.submit = Đăng nhập
     

    text_nl.properties(chứa nlcặp khóa-giá trị tiếng Hà Lan ( ))

     login.label.username = Gebruikersnaam
     login.label.password = Wachtwoord
     login.button.submit = Inloggen
     

    text_es.properties(chứa escặp khóa-giá trị tiếng Tây Ban Nha ( ))

     login.label.username = Nombre de usuario
     login.label.password = Contraseña
     login.button.submit = Acceder
     

    Tên tệp gói tài nguyên phải tuân theo mẫu sau name_ll_CC.properties. Phần _llnày phải là mã ngôn ngữ ISO 693-1 chữ thường . Nó là tùy chọn và chỉ được yêu cầu bất cứ khi nào _CCphần này có mặt. Phần _CCphải là mã quốc gia ISO 3166-1 Alpha-2 viết hoa . Nó là tùy chọn và thường chỉ được sử dụng để phân biệt giữa các phương ngữ ngôn ngữ cụ thể của quốc gia, như tiếng Anh Mỹ ( _en_US) và tiếng Anh Anh ( _en_GB).


  2. Nếu vẫn chưa hoàn tất, hãy cài đặt JSTL. Nếu bạn đang chạy trên vùng chứa Servlet 2.5 hoặc mới hơn (Tomcat 6.0, v.v.) và của bạn web.xmlđược tuyên bố là phù hợp với đặc tả Servlet 2.5, thì chỉ cần đặt jstl-1.2.jar vào /WEB-INF/libthư mục của webapp .


  3. Tạo tệp JSP mẫu sau và đặt nó trong thư mục nội dung web.

    login.jsp

     <%@ page pageEncoding="UTF-8" %>
     <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
     <c:set var="language" value="${not empty param.language ? param.language : not empty language ? language : pageContext.request.locale}" scope="session" />
     <fmt:setLocale value="${language}" />
     <fmt:setBundle basename="com.example.i18n.text" />
     <!DOCTYPE html>
     <html lang="${language}">
         <head>
             <title>JSP/JSTL i18n demo</title>
         </head>
         <body>
             <form>
                 <select id="language" name="language" onchange="submit()">
                     <option value="en" ${language == 'en' ? 'selected' : ''}>English</option>
                     <option value="nl" ${language == 'nl' ? 'selected' : ''}>Nederlands</option>
                     <option value="es" ${language == 'es' ? 'selected' : ''}>Español</option>
                 </select>
             </form>
             <form method="post">
                 <label for="username"><fmt:message key="login.label.username" />:</label>
                 <input type="text" id="username" name="username">
                 <br>
                 <label for="password"><fmt:message key="login.label.password" />:</label>
                 <input type="password" id="password" name="password">
                 <br>
                 <fmt:message key="login.button.submit" var="buttonValue" />
                 <input type="submit" name="submit" value="${buttonValue}">
             </form>
         </body>
     </html>
    

    Các <c:set var="language">quản lý ngôn ngữ hiện tại. Nếu ngôn ngữ được cung cấp dưới dạng tham số yêu cầu (theo ngôn ngữ thả xuống), thì ngôn ngữ đó sẽ được đặt. Nếu ngôn ngữ khác đã được đặt trước đó trong phiên, thì thay vào đó hãy sử dụng ngôn ngữ đó. Khác sử dụng ngôn ngữ do người dùng cung cấp trong tiêu đề yêu cầu.

    Bộ <fmt:setLocale>định vị cho gói tài nguyên. Điều quan trọng là dòng này là trước khi các <fmt:setBundle>.

    Khởi <fmt:setBundle>tạo gói tài nguyên theo tên cơ sở của nó (nghĩa là tên gói đủ điều kiện đầy đủ cho đến khi có tên duy nhất không có mã _ll_CCđịnh nghĩa).

    Việc <fmt:message>truy xuất giá trị thông báo bằng khóa gói được chỉ định.

    <html lang="${language}">thông báo cho các rô bốt tìm kiếm ngôn ngữ của trang để nó không bị đánh dấu là nội dung trùng lặp (do đó, tốt cho SEO).

    Trình đơn ngôn ngữ thả xuống sẽ được JavaScript gửi ngay lập tức khi ngôn ngữ khác được chọn và trang sẽ được làm mới bằng ngôn ngữ mới được chọn.


Tuy nhiên, bạn cần lưu ý rằng các tệp thuộc tính được đọc theo mặc định bằng cách sử dụng mã hóa ký tự ISO-8859-1. Bạn sẽ cần phải thoát khỏi chúng bằng cách thoát unicode. Điều này có thể được thực hiện bằng cách sử dụng native2ascii.execông cụ do JDK cung cấp . Xem thêm phần bài viết này để biết thêm chi tiết.

Một giải pháp thay thế trên lý thuyết sẽ là cung cấp một gói có tùy chỉnh Controlđể tải các tệp đó dưới dạng UTF-8, nhưng rất tiếc điều đó không được hỗ trợ bởi fmttaglib JSTL cơ bản . Bạn sẽ cần phải tự mình quản lý tất cả với sự trợ giúp của a Filter. Có những khung công tác (MVC) có thể xử lý điều này theo cách minh bạch hơn, như JSF, hãy xem thêm bài viết này .


2
Giải pháp hay này có một vấn đề: ngôn ngữ được lấy từ yêu cầu có thể là ngôn ngữ và quốc gia, như trong "en_US", sẽ cung cấp cho <html lang = "en_US">, là HTML không hợp lệ. Chỉ cần sử dụng phần ngôn ngữ "en" từ ngôn ngữ làm giá trị cho thuộc tính lang.
Torsten Römer

1
Phương pháp nêu trên để quốc tế hóa không sửa đổi url dựa trên ngôn ngữ được hiển thị. Bạn có gợi ý nào về cách cập nhật url theo ngôn ngữ không. Tôi yêu cầu vì để lập chỉ mục, các ngôn ngữ khác nhau nên có các url riêng biệt: support.google.com/webmasters/answer/…
theyuv 23/02/16

1
Nếu bạn đặt các tệp tài nguyên ngôn ngữ (tệp test.properties và text_en.properties) tại gốc ứng dụng / tài nguyên, bạn có thể đặt fmt: pack như sau: <fmt: setBundle basename = "text" />
Bahadir Tasdemir

1
@bahadirT: giả sử "test" là lỗi đánh máy, điều đó chính xác. Các basenamephải đại diện cho tên cơ sở mà không cần phần mở rộng tập tin. Không cấu trúc nó trong một gói chỉ là một thực hành kém.
BalusC

1
@theyuv: User has {0} review{0,choice,0#s|1#|1<s} docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html
BalusC

26

Ngoài những gì BalusC đã nói, bạn phải quan tâm đến tính định hướng (vì tiếng Anh được viết từ Trái sang Phải và tiếng Ả Rập ngược lại). Cách dễ nhất là thêm dirthuộc tính vào htmlphần tử của trang web JSP của bạn và ngoại hóa nó, vì vậy giá trị đến từ tệp thuộc tính (giống như với các phần tử hoặc thuộc tính khác):

<html dir="${direction}">
...
</html>

Ngoài ra, có một số vấn đề với việc tạo kiểu ứng dụng như vậy - bạn nên nói rằng ít nhất là tránh vị trí tuyệt đối. Nếu bạn không thể tránh điều đó vì một lý do, bạn có thể sử dụng stylesheets khác nhau cho mỗi (mỗi?) Ngôn ngữ hoặc làm điều gì đó có nghĩa là verboten , đó là bảng sử dụng để quản lý bố trí. Nếu bạn muốn sử dụng các phần tử div, tôi khuyên bạn nên sử dụng định vị tương đối với các thuộc tính kiểu trái và phải "đối xứng" (cả hai đều có cùng giá trị), vì đây là điều làm cho hướng chuyển đổi hoạt động.

Bạn có thể tìm thêm về các trang web Bi-Directional tại đây .


7
Vâng, thực sự, điều đó cũng phải được tính đến.
BalusC

4
<html dir="RTL">HOẶC <html dir="LTR">. Mặc định là<html dir="LTR">
Fahim Parkar

2

dựa trên hướng dẫn này , tôi đang sử dụng phần sau trên GAE - Công cụ ứng dụng của Google:

Một tệp jsp như sau:

<%@ page import="java.io.* %>
<% 
  String lang = "fr"; //Assign the correct language either by page or user-selected or browser language etc.
  ResourceBundle RB = ResourceBundle.getBundle("app", new Locale(lang));
%>                 

<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<head>
</head>
<body>
  <p>      
    <%= RB.getString("greeting") %>
  </p>
</body>

Và thêm các tệp có tên: app.properties(mặc định) và app_fr.properties(v.v. cho mọi ngôn ngữ). Mỗi tệp này phải chứa các chuỗi bạn cần như sau: key: value_in_language, ví dụ: app_fr.propertieschứa:

greeting=Bonjour!

app.properties chứa đựng:

greeting=Hello!

Đó là tất cả


10
Rất tiếc, Scriptlets!
Nestor Hernandez Loli
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.