Bugun biz ko'p tillilik haqida gaplashamiz. Xo'sh, bu nima?
Ko'p tillilik, boshqacha aytganda,
xalqarolashtirish , dastur mantig'ini o'zgartirmasdan bir nechta tillarga moslashtirilishi mumkin bo'lgan dasturni ishlab chiqishning bir qismidir. Vaziyatni ko'rib chiqing: siz, masalan, rus, ingliz va ispan tillarida so'zlashadigan ko'plab mamlakatlar aholisi uchun yirik savdo kompaniyasi uchun veb-ilovani yaratyapsiz. Siz uni barcha foydalanuvchilar uchun qulay qilishingiz kerak. G'oya shunday: rus tilida so'zlashuvchi o'quvchi sizning ma'lumotlaringizni rus tilida ko'rish imkoniyatiga ega bo'lishi kerak, amerikalik uchun materialni ingliz tilida o'qish qulayroq bo'ladi va ispaniyalik uchun - ispan tilida (kutilmaganda, shunday emasmi?)
Bugungi kunda
bir nechta xalqarolashtirish modellarini ko'rib chiqamiz va ulardan biri uchun (bu menga eng yoqadi :) Keling, Java-da amalga oshirishni ko'rib chiqaylik. Gvineya cho'chqasi sifatida bugun bizda kino ma'lumotlar taxtasi bo'ladi. Keling, juda buzuq bo'lib qolmaylik, shuning uchun bizda ko'p ma'ruzachilar bo'lmaydi. Masalan, bu yaxshi. Va biz filmlarning nomlarini tarjima qilamiz (rejissyorlar - qo'shimchalar uchun):
1. Har bir til uchun tarjimasi bilan jadval
Ushbu modelning mohiyati: har bir tilda ma'lumotlar bazasida tarjimani talab qiladigan barcha katakchalarni o'z ichiga olgan alohida jadval mavjud. Bu usulning kamchiligi shundaki, har safar yangi til qo‘shganda yangi jadval qo‘shishimiz kerak bo‘ladi. Ya'ni, bizning mijozimiz juda yaxshi ishlayapti, deb tasavvur qilaylik va u o'z ilovasini dunyoning ko'plab mamlakatlarida (aslida, tillarda) kengaytirmoqda. Bu shuni anglatadiki, har bir til uchun bitta tabletka qo'shishingiz kerak bo'ladi. Natijada, biz yarim yoki deyarli butunlay yordamchi tarjima jadvallaridan iborat ma'lumotlar bazasiga ega bo'lamiz:
Filmlarning o'zlari sxemasi: Tarjima jadvallari:
2. Hamma uchun bitta
Muayyan modelga tegishli bo'lgan har bir jadvalda til plitasi uchun identifikatorli maydon qo'shiladi. Shunga ko'ra, ma'lumotlar bazasida ushbu jadval tarjimalari bilan ham mavjud. Muammo shundaki, bitta ob'ekt bir nechta tarjimalarga (tillarga) mos kelishi mumkin. Natijada, sub'ektlarning takrorlanishi bo'ladi va bu mantiqni juda chalkashtirib yuboradi va murakkablashtiradi va bu yaxshi emas.
Biz UML ga qaraymiz: Stol filmlari: Jadval tillari:
3. Til boshiga ustun
Jadvaldagi har bir til uchun har bir ustun uchun alohida tarjima ustuni yaratiladi. Ushbu yondashuvning kamchiligi shundaki, agar yana ko'p sonli tillar qo'shilsa, ma'lumotlar bazasi strukturasini har safar o'zgartirish kerak bo'ladi va bu yomon yondashuv hisoblanadi. Shuningdek, xalqarolashtirishni talab qiluvchi belgilar qanchalik ko'payganligini tasavvur qiling. Qo'llab-quvvatlanadigan tillar soni oldindan ma'lum bo'lgan modelni ko'rib chiqishga arziydi, ular juda ko'p emas va har bir model barcha til o'zgarishlarida mavjud bo'lishi kerak.
UML: Hammasini o'z ichiga olgan jadval:
4. Tashqi tarjima
Ushbu parametr tashqi vositalarni (Google translate, Bing translate va boshqalar) ulash orqali amalga oshiriladi. Agar iloji boricha ko'proq tashrif buyuruvchilarga ma'lumot berish kerak bo'lsa va bu ma'lumotlar juda ko'p bo'lsa ishlatiladi. Juda ko'p. Bunday holda siz barcha tillarda ma'lumotlar bazasida ma'lumotlarni to'g'ridan-to'g'ri saqlashga emas, balki uni dinamik ravishda tarjima qilishga qaror qilishingiz mumkin. Ammo shuni esda tutish kerakki, mashina tarjimasi sifati ko'pincha orzu qilingan narsalarni qoldiradi. Variantni faqat juda tejamkor deb hisoblash mumkin (har bir nashrni tarjima qilish uchun resurslar mavjud bo'lmaganda). To‘g‘ri tarjima qilish borasida keng tarqalgan muammo shundaki, tilni yaxshi bilmaydigan tarjimonlar so‘zning noto‘g‘ri ma’nosini tanlab, foydalanuvchini chalg‘itib, tugmachada yozilgan narsaning ma’nosini mustaqil aniqlashga majbur qiladi. Gapni nafaqat toʻgʻri tarjima qilish, balki uning maʼnosini maʼlum bir til va millatga moslashtirish ham muhim ahamiyatga ega. Ishlab chiquvchilarda ba'zi tillarda jinslar bilan bog'liq muammolar ko'p. Ular foydalanuvchi jinsiga qarab koddagi iborani takrorlashlari kerak, shuningdek, nafaqat otlar jinsga ega, balki sifatlar va fe'llarning ham turlicha flektivlanishini hisobga olishlari kerak. Ilovada ingliz tilidan boshqa tilni tanlagan holda, tanlangan tilning so'zlari bilan birga hali ham tarjima qilinmagan elementlar mavjud bo'lgan holatlar mavjud. Agar bir nechta tillar ko'rsatilsa va u o'ziga xos Bobil bo'lib chiqsa, bundan ham yomoni, u erda hamma narsa aralashib ketgan va foydalanuvchi dasturni tushunolmasa. Masalan:
https://cloud.google.com/translate/
5. Ilova darajasidagi qo'llab-quvvatlash fayllari
Tarjimalarni saqlash uchun alohida fayllar yaratiladi. Bu har bir til uchun bitta fayl yoki har bir planshet uchun bitta fayl bo'lishi mumkin (nozik maydalash). Ushbu parametr ko'pincha ushbu fayllarda ko'plab matnlar saqlanishi mumkinligi sababli ishlatiladi, ya'ni jadvallar va ma'lumotlar bazasi o'zi shishib ketmaydi. Yana bir qulaylik shundaki, siz ushbu maydonlar uchun ma'lumotlar bazasini taqillatishingiz shart emas va koddagi fayllar so'ralgan tilga qarab dinamik ravishda almashtirilishi mumkin. Natijada, fayl biz uchun lug'at bo'lib xizmat qiladi, unda kalit til, qiymat matn hisoblanadi. Lekin biz quyida keltirilgan ".properties" formati bilan cheklanmaymiz va bu fayl formatlari juda katta farq qilishi mumkin - JSON, XML va boshqalar. Kamchiliklari shundaki, bu holda ma'lumotlar bazasini normallashtirish juda kamayadi. Bundan tashqari, ma'lumotlarning yaxlitligi endi faqat ma'lumotlar bazasiga bog'liq emas, balki serializatsiya mexanizmiga ham bog'liq.
Ushbu mavzu bo'yicha ajoyib maqola Tarjimalar bilan lug'at fayllariga misol:
6. Har bir jadval uchun yordamchi tarjima jadvali
Menimcha, eng moslashuvchan yechim. Ushbu yondashuvning mohiyati tillar uchun alohida jadval yaratishdir. Ko'rib chiqilayotgan jadval uchun tarjima qilish imkoniyatini amalga oshirish zarur bo'lganda, til jadvali bilan havola yaratiladi va havolalar jadvalida til identifikatori, element identifikatori va tarjimalar bilan ustunlar mavjud. Bu ko'rinadigan darajada qo'rqinchli emas. Ushbu yondashuv qo'llab-quvvatlanadigan tillarning juda moslashuvchan kengaytirilishiga imkon beradi. Keling, batafsil ko'rib chiqaylik.
UML: Filmlar bilan jadval: Tillar jadvali: Tarjimalar jadvali: Va yuqorida aytganimdek, Java kodidagi variantlardan birini amalga oshirishni ko'rib chiqamiz (siz tushunganingizdek, bu oxirgi variant bo'ladi). Ilovaning o'zida bunday narsa yo'q: biz kontrollerlardan tao qatlamlariga o'tamiz. Biz yaratish usulini ko'rib chiqamiz - misol uchun bu etarli bo'ladi. Shunday ekan, ketaylik)) Bizning mohiyatimiz film:
@Builder
@Getter
public class Movie {
private Long id;
private String producer;
}
Hech narsa qiziq emas, faqat birinchi jadvalning modelini amalga oshirish.
dto (Ma'lumotlarni uzatish ob'ekti) konvertorlari bilan boshqaruvchi:
@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();
}
}
DTOda biz tarjimalarni xarita sifatida o'tkazamiz, kalit til qisqartmasi, qiymat tarjima qiymati (film nomi).
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;
}
Bu erda biz dto sinfining o'zini ko'ramiz, yuqorida yozilganidek, tarjimalar uchun xarita, qolgan maydonlar Film modelining ekranidir.Keling,
kino xizmatiga o'tamiz:
public interface MovieService {
Movie create(Movie movie, Map nameList);
}
Uning amalga oshirilishi:
@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;
}
}
Bu erda biz til identifikatorini qisqartmasi bo'yicha olish uchun nisbatan uchinchi tomon LanguageService xizmatidan foydalanishni ko'ramiz. Va bu identifikator yordamida biz tarjimalarimizni (shuningdek, xarita shaklida) ulanish jadvaliga saqlaymiz.
Keling, DAO ni ko'rib chiqaylik:
public interface MovieDAO {
void create(Movie movie);
void createTranslator(Long movieId, Map<Long,String> nameTranslations);
}
Amalga oshirish:
@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));
}
}
Bu erda biz uning mohiyati va tillarining saqlanishini ko'ramiz (lug'at). Ha, bu erda Spring JDBC ishlatiladi: men buni yangi boshlanuvchilar uchun afzal deb bilaman, chunki u shaffofroq. Keling, "uchinchi tomon" xizmatiga o'tamiz.
Til xizmati:
public interface LanguageService {
Long getIdByLangCode(String lang);
}
Amalga oshirish:
@Service
@RequiredArgsConstructor
public class LanguageServiceImpl implements LanguageService {
private final LanguageDAO languageDAO;
@Override
public Long getIdByLangCode(String lang) {
return languageDAO.getIdByLangCode(lang);
}
}
Hech qanday maxsus narsa yo'q, qisqartirilgan nom bo'yicha qidiring.
DAO:
public interface LanguageDAO {
Long getIdByLangCode(String lang);
}
Amalga oshirish:
@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);
}
}
Tuzilishi: Yuqorida tavsiflangan barcha modellar yashash huquqiga ega. Vaziyatga qarab qaysi birini ishlatishni hal qilishingiz kerak. Albatta, bu hammasi emas: yana ko'p turli xil yondashuvlar mavjud, jumladan, turli tillar uchun turli ma'lumotlar bazalaridan foydalanish, keshlardan foydalanish, turli ramkalar va boshqalar. Bugun men uchun hammasi shu va...
GO TO FULL VERSION