JavaRush /مدونة جافا /Random-AR /تنفيذ تطبيق متعدد اللغات

تنفيذ تطبيق متعدد اللغات

نشرت في المجموعة
تنفيذ تطبيق متعدد اللغات - 1

اليوم سنتحدث عن التعددية اللغوية. إذا ما هو؟

تعدد اللغات، بمعنى آخر، التدويل ، هو جزء من تطوير تطبيق يمكن تكييفه لعدة لغات دون تغيير منطق البرنامج. خذ بعين الاعتبار الموقف: أنت تقوم بإنشاء تطبيق ويب لشركة تجارية كبيرة للمقيمين في عدد كبير من البلدان، على سبيل المثال، يتم التحدث بلغات مثل الروسية والإنجليزية والإسبانية. تحتاج إلى جعلها مريحة لجميع المستخدمين. الفكرة هي كما يلي: يجب أن يكون القارئ الناطق بالروسية قادرًا على رؤية بياناتك باللغة الروسية، وسيكون الأمريكي أكثر راحة عند قراءة المادة باللغة الإنجليزية، والإسباني - باللغة الإسبانية (بشكل غير متوقع، أليس كذلك؟) دعونا نفكر في العديد من نماذج التدويلتنفيذ تطبيق متعدد اللغات - 2 اليوم وواحد منهم (وهو أكثر ما يعجبني :) دعونا نلقي نظرة على التنفيذ في Java. باعتبارنا خنزير غينيا، سيكون لدينا اليوم لوحة بيانات الفيلم. دعونا لا ننحرف كثيرًا، حتى لا يكون لدينا الكثير من المتحدثين. على سبيل المثال، هذا جيد. وسوف نقوم بترجمة أسماء الأفلام (المخرجين - للإضافات): تنفيذ تطبيق متعدد اللغات - 3

1. جدول مع الترجمة لكل لغة

جوهر هذا النموذج: كل لغة لديها جدول منفصل في قاعدة البيانات، والذي يحتوي على جميع الخلايا التي تتطلب الترجمة. عيب هذه الطريقة هو أنه في كل مرة نضيف فيها لغة جديدة، نحتاج إلى إضافة جدول جديد. أي لنتخيل أن أداء عميلنا جيد جدًا، ويقوم بتوسيع نطاق تطبيقه ليشمل العديد من البلدان (في الواقع اللغات) في العالم. هذا يعني أنك ستحتاج إلى إضافة قرص واحد لكل لسان. ونتيجة لذلك، سيكون لدينا نصف قاعدة بيانات أو شبه كاملة تتكون من جداول الترجمة المساعدة: تنفيذ تطبيق متعدد اللغات - 4 رسم تخطيطي للأفلام نفسها: تنفيذ تطبيق متعدد اللغات - 5جداول الترجمة:
  • الروسية تنفيذ تطبيق متعدد اللغات - 6
  • الأسبانية تنفيذ تطبيق متعدد اللغات - 7
  • إنجليزي تنفيذ تطبيق متعدد اللغات - 8

2. واحد للجميع

في كل جدول ينتمي إلى نموذج معين، يتم إضافة حقل بمعرف لوحة اللغة. وبناءً على ذلك، تحتوي قاعدة البيانات أيضًا على هذا الجدول مع الترجمات. المشكلة هي أن كائنًا واحدًا يمكن أن يتوافق مع عدة ترجمات (لغات). ونتيجة لذلك، سيكون هناك ازدواجية في الكيانات، وهذا يربك المنطق ويعقده بشكل كبير، وهذا ليس جيدًا. نحن ننظر إلى UML: تنفيذ تطبيق متعدد اللغات - 9 أفلام الجدول: تنفيذ تطبيق متعدد اللغات - 10 لغات الجدول: تنفيذ تطبيق متعدد اللغات - 11

3. عمود لكل لسان

يتم إنشاء عمود ترجمة منفصل لكل عمود لكل لغة في الجدول. عيب هذا الأسلوب هو أنه، مرة أخرى، إذا تمت إضافة عدد كبير من اللغات، فستحتاج بنية قاعدة البيانات إلى التغيير في كل مرة، ويعتبر هذا أسلوبًا سيئًا. وتخيل أيضًا مدى تضخيم اللافتات المطالبة بالتدويل. قد يكون من المفيد النظر في نموذج يكون فيه عدد اللغات المدعومة معروفًا مسبقًا، ولا يوجد الكثير منها، ويجب أن يكون كل نموذج موجودًا في جميع أشكال اللغة المختلفة. UML: تنفيذ تطبيق متعدد اللغات - 12جدول شامل: تنفيذ تطبيق متعدد اللغات - 13

4. الترجمة الخارجية

يتم تنفيذ هذا الخيار من خلال ربط الأدوات الخارجية (ترجمة جوجل، ترجمة بنج، وما إلى ذلك). يتم استخدامه إذا كنت بحاجة إلى توفير المعلومات لأكبر عدد ممكن من الزوار، وهناك الكثير من هذه المعلومات. كثير جدا. في هذه الحالة، يمكنك أن تقرر عدم تخزين المعلومات مباشرة في قاعدة البيانات بجميع اللغات، ولكن ترجمتها ديناميكيًا. ولكن تجدر الإشارة إلى أن جودة الترجمة الآلية غالباً ما تترك الكثير مما هو مرغوب فيه. لا يمكن اعتبار هذا الخيار إلا اقتصاديًا للغاية (عندما لا تكون هناك موارد لترجمة كل منشور). إحدى المشاكل الشائعة فيما يتعلق بالترجمة الصحيحة هي أن المترجمين الذين لا يعرفون اللغة جيدًا يختارون المعنى الخاطئ للكلمة ويربكون المستخدم، مما يجبره على اكتشاف معنى ما هو مكتوب على الزر بشكل مستقل. ومن المهم أيضًا ليس فقط ترجمة الجملة بشكل صحيح، ولكن أيضًا إيصال معناها إلى لغة وجنسية معينة. يواجه المطورون الكثير من المشاكل مع الأجناس في بعض اللغات. يجب عليهم تكرار العبارة في الكود اعتمادًا على جنس المستخدم، ويأخذون في الاعتبار أيضًا أنه ليس فقط الأسماء لها جنس، ولكن أيضًا الصفات والأفعال يتم تصريفها بشكل مختلف. هناك حالات عندما تختار لغة أخرى غير الإنجليزية في التطبيق، إلى جانب كلمات اللغة المحددة، لا تزال هناك عناصر غير مترجمة. والأسوأ من ذلك إذا تم عرض عدة لغات وتبين أنها نوع من بابل، حيث يختلط كل شيء ولا يستطيع المستخدم فهم التطبيق، على سبيل المثال: https://cloud.google.com/translate/

5. ملفات الدعم على مستوى التطبيق

يتم إنشاء ملفات منفصلة لتخزين الترجمات. يمكن أن يكون ملفًا واحدًا لكل لسان أو ملفًا واحدًا لكل لسان لكل قرص (سحق ناعم). غالبا ما يستخدم هذا الخيار لأنه يمكن تخزين العديد من النصوص في هذه الملفات، مما يعني أن الجداول وقاعدة البيانات نفسها لن تصبح منتفخة. ميزة أخرى هي أنك لا تحتاج إلى النقر على قاعدة البيانات لهذه الحقول، ويمكن استبدال الملفات الموجودة في التعليمات البرمجية ديناميكيًا اعتمادًا على اللغة المطلوبة. نتيجة لذلك، يعمل الملف بمثابة قاموس بالنسبة لنا، حيث يكون المفتاح هو اللغة، والقيمة هي النص. لكننا لا نقتصر على تنسيق ".properties" أدناه، ويمكن أن تختلف تنسيقات الملفات هذه بشكل كبير - JSON، وXML، وما إلى ذلك. تتمثل العيوب في أنه في هذه الحالة يتم تقليل تطبيع قاعدة البيانات بشكل كبير. كما أن سلامة البيانات لم تعد تعتمد فقط على قاعدة البيانات، بل أيضًا على آلية التسلسل. مقالة ممتازة حول هذا الموضوع مثال لملفات القاموس مع الترجمات: تنفيذ تطبيق متعدد اللغات - 14
  • إنجليزي تنفيذ تطبيق متعدد اللغات - 15
  • الروسية تنفيذ تطبيق متعدد اللغات - 16
  • الأسبانية تنفيذ تطبيق متعدد اللغات - 17

6. جدول الترجمة المساعد لكل جدول

في رأيي، الحل الأكثر مرونة. جوهر هذا النهج هو إنشاء جدول منفصل للغات. عندما يكون من الضروري تنفيذ إمكانية الترجمات للجدول المعني، يتم إنشاء رابط مع جدول اللغة، ويحتوي جدول الارتباط على معرف اللغة ومعرف العنصر والأعمدة مع الترجمات. انها ليست مخيفة كما يبدو. يسمح هذا الأسلوب بتوسيع مرن إلى حد ما للغات المدعومة. دعونا نلقي نظرة فاحصة. UML: تنفيذ تطبيق متعدد اللغات - 18جدول بالأفلام: تنفيذ تطبيق متعدد اللغات - 19جدول اللغات: تنفيذ تطبيق متعدد اللغات - 20جدول الترجمات: تنفيذ تطبيق متعدد اللغات - 21 وكما قلت أعلاه، دعونا نلقي نظرة على تنفيذ أحد الخيارات في كود Java (كما تفهم، سيكون هذا هو الخيار الأخير). لا يوجد شيء من هذا القبيل في التطبيق نفسه: سننتقل من وحدات التحكم إلى طبقات الداو. سنلقي نظرة على طريقة الإنشاء - على سبيل المثال هذا يكفي. فلنذهب)) جوهرنا هو الفيلم:
@Builder
@Getter
public class Movie {

   private Long id;

   private String producer;
}
لا شيء مثير للاهتمام، فقط قم بتنفيذ نموذج الجدول الأول. وحدة التحكم مع محولات dto (كائن نقل البيانات):
@RestController
@RequiredArgsConstructor
@RequestMapping(path = "/cities")
public class MovieController {

   private final MovieService movieService;

   @PostMapping
   public ResponseEntity<moviedto> create(MovieDTO movieDTO) {
       return new ResponseEntity<>(toDTO(movieService.create(fromDTO(movieDTO), movieDTO.getNameTranslations()), movieDTO.getNameTranslations()), HttpStatus.CREATED);
   }

   private Movie fromDTO(MovieDTO dto) {
       return Movie.builder()
               .id(dto.getId())
               .producer(dto.getProducer())
               .build();
   }

   private MovieDTO toDTO(Movie movie, Map<string, string=""> nameTranslation) {
       return MovieDTO.builder()
               .id(movie.getId())
               .producer(movie.getProducer())
               .nameTranslations(nameTranslation)
               .build();
   }
}
في DTO نقوم بتمرير الترجمات كخرائط، والمفتاح هو اختصار اللغة، والقيمة هي قيمة الترجمة (اسم الفيلم). DTO:
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class MovieDTO {

   @JsonProperty("id")
   private Long id;

   @JsonProperty("name")
   private String producer;

   @JsonProperty("nameTranslations")
   private Map<String, String> nameTranslations;//example = "{'en': 'The Matrix', 'ru' : 'Матрица'}"
}
هنا نرى فئة dto نفسها، كما هو مكتوب أعلاه، خريطة للترجمات، الحقول المتبقية هي عرض لنموذج الفيلم، دعنا ننتقل إلى خدمة الأفلام:
public interface MovieService {

   Movie create(Movie movie, Map nameList);
}
تنفيذها:
@Service
@RequiredArgsConstructor
public class MovieServiceImpl implements MovieService {

   private final MovieDAO movieDAO;
   private LanguageService languageService;

   @Override
   public Movie create(Movie movie, Map<string, string=""> nameList) {
       movieDAO.create(movie);
       Map<Long, String> map = new HashMap<>();
       nameList.forEach((x, y) -> map.put(languageService.getIdByLangCode(x), y));
       movieDAO.createTranslator(movie.getId(), map);
       return movie;
   }
}
نرى هنا استخدام خدمة LanguageService تابعة لجهة خارجية نسبيًا لاسترداد معرف اللغة من خلال اختصاره. وباستخدام هذا المعرف نقوم بحفظ ترجماتنا (أيضًا على شكل خريطة) في جدول الاتصال. دعونا نلقي نظرة على DAO:
public interface MovieDAO {

   void create(Movie movie);

   void createTranslator(Long movieId, Map<Long,String> nameTranslations);
}
تطبيق:
@RequiredArgsConstructor
@Repository
public class MovieDAOImpl implements MovieDAO {
   private final JdbcTemplate jdbcTemplate;

   private static final String CREATE_MOVIE = "INSERT INTO movies(id, producer) VALUES(?, ?)";

   private static final String CREATE_TRANSLATOR = "INSERT INTO movies_translator(movies_id, language_id, name) VALUES(?, ?, ?)";

   @Override
   public void create(Movie movie) {
       jdbcTemplate.update(CREATE_MOVIE, movie.getId(), movie.getProducer());
   }

   @Override
   public void createTranslator(Long movieId, Map<Long, String> nameTranslations) {
       nameTranslations.forEach((x, y) -> jdbcTemplate.update(CREATE_TRANSLATOR, movieId, x, y));
   }
}
وهنا نرى الحفاظ على الجوهر واللغات الخاصة به (القاموس). ونعم، يتم استخدام Spring JDBC هنا: أنا أعتبره أفضل للمبتدئين، لأنه أكثر شفافية. دعنا ننتقل إلى خدمة "الطرف الثالث". خدمة اللغة:
public interface LanguageService {

   Long getIdByLangCode(String lang);
}
تطبيق:
@Service
@RequiredArgsConstructor
public class LanguageServiceImpl implements LanguageService {
   private final LanguageDAO languageDAO;

   @Override
   public Long getIdByLangCode(String lang) {
       return languageDAO.getIdByLangCode(lang);
   }
}
لا شيء مميز، ابحث بالاسم المختصر. داو:
public interface LanguageDAO {

   Long getIdByLangCode(String lang);
}
تطبيق:
@RequiredArgsConstructor
@Repository
public class LanguageDAOImpl implements LanguageDAO {
   private final JdbcTemplate jdbcTemplate;

   private static final String FIND_ID_BY_LANG_CODE = "SELECT id FROM languages WHERE lang_code = ?";

   @Override
   public Long getIdByLangCode(String lang) {
       return jdbcTemplate.queryForObject(FIND_ID_BY_LANG_CODE, Long.class, lang);
   }
}
الهيكل: تنفيذ تطبيق متعدد اللغات - 23 جميع النماذج الموصوفة أعلاه لها الحق في الحياة. عليك أن تقرر أي واحد ستستخدمه بناءً على الموقف. بالطبع، هذا ليس كل شيء: هناك العديد من الأساليب المختلفة، بما في ذلك استخدام قواعد بيانات مختلفة للغات مختلفة، واستخدام ذاكرات التخزين المؤقت، وأطر العمل المختلفة، وما إلى ذلك. هذا كل شيء بالنسبة لي اليوم و... تنفيذ تطبيق متعدد اللغات - 24
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION