| @@ -1,34 +1,34 @@ | |||||
| # Created by .ignore support plugin (hsz.mobi) | |||||
| ### Java template | |||||
| # Compiled class file | |||||
| *.class | |||||
| HELP.md | |||||
| target/ | |||||
| !.mvn/wrapper/maven-wrapper.jar | |||||
| !**/src/main/**/target/ | |||||
| !**/src/test/**/target/ | |||||
| logs/** | |||||
| # Log file | |||||
| *.log | |||||
| ### STS ### | |||||
| .apt_generated | |||||
| .classpath | |||||
| .factorypath | |||||
| .project | |||||
| .settings | |||||
| .springBeans | |||||
| .sts4-cache | |||||
| # BlueJ files | |||||
| *.ctxt | |||||
| # Mobile Tools for Java (J2ME) | |||||
| .mtj.tmp/ | |||||
| # Package Files # | |||||
| *.jar | |||||
| *.war | |||||
| *.nar | |||||
| *.ear | |||||
| *.zip | |||||
| *.tar.gz | |||||
| *.rar | |||||
| # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | |||||
| hs_err_pid* | |||||
| ### Example user template template | |||||
| ### Example user template | |||||
| # IntelliJ project files | |||||
| ### IntelliJ IDEA ### | |||||
| .idea | .idea | ||||
| *.iws | |||||
| *.iml | *.iml | ||||
| out | |||||
| gen | |||||
| *.ipr | |||||
| ### NetBeans ### | |||||
| /nbproject/private/ | |||||
| /nbbuild/ | |||||
| /dist/ | |||||
| /nbdist/ | |||||
| /.nb-gradle/ | |||||
| build/ | |||||
| !**/src/main/**/build/ | |||||
| !**/src/test/**/build/ | |||||
| ### VS Code ### | |||||
| .vscode/ | |||||
| @@ -0,0 +1,26 @@ | |||||
| package com.iformall.controller; | |||||
| import com.iformall.annotation.AuthIgnore; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.dto.neuver.GetLanguageDTO; | |||||
| import com.iformall.service.sm.VoiceLanguageService; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.annotation.PostMapping; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import org.springframework.web.bind.annotation.RequestMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| @RestController | |||||
| @RequestMapping("/api/VoiceLanguage") | |||||
| public class VoiceLanguageController { | |||||
| @Autowired | |||||
| private VoiceLanguageService voiceLanguageService; | |||||
| @ApiOperation("根据文案获取语种") | |||||
| @PostMapping("getLanguage") | |||||
| public ResultData getLanguage(@RequestBody GetLanguageDTO dto) { | |||||
| return new ResultData(voiceLanguageService.getLanguage(dto.getPaperwork())); | |||||
| } | |||||
| } | |||||
| @@ -76,12 +76,12 @@ public class GlobalDefultExceptionHandler { | |||||
| logger.error("************************异常开始*******************************"); | logger.error("************************异常开始*******************************"); | ||||
| if(checkExceptionType(ex)) { | if(checkExceptionType(ex)) { | ||||
| // 特殊异常不打印堆栈 | // 特殊异常不打印堆栈 | ||||
| logger.error(ex.getMessage()); | |||||
| logger.error("message:" + ex); | |||||
| logger.error("************************异常结束*******************************"); | logger.error("************************异常结束*******************************"); | ||||
| return; | return; | ||||
| } | } | ||||
| logger.error("请求地址:" + request.getRequestURL()); | logger.error("请求地址:" + request.getRequestURL()); | ||||
| logger.error("message:"+ ex.getMessage()); | |||||
| logger.error("message:"+ ex); | |||||
| Enumeration enumeration = request.getParameterNames(); | Enumeration enumeration = request.getParameterNames(); | ||||
| logger.error("请求参数"); | logger.error("请求参数"); | ||||
| while (enumeration.hasMoreElements()) { | while (enumeration.hasMoreElements()) { | ||||
| @@ -0,0 +1,12 @@ | |||||
| package com.iformall.domain.dto.neuver; | |||||
| import io.swagger.annotations.ApiModel; | |||||
| import io.swagger.annotations.ApiModelProperty; | |||||
| import lombok.Data; | |||||
| @ApiModel(value = "获取语种") | |||||
| @Data | |||||
| public class GetLanguageDTO { | |||||
| @ApiModelProperty(value = "文案") | |||||
| private String paperwork; | |||||
| } | |||||
| @@ -6,8 +6,31 @@ import com.iformall.domain.po.sm.VoiceLanguage; | |||||
| import org.apache.ibatis.annotations.Param; | import org.apache.ibatis.annotations.Param; | ||||
| import java.util.HashSet; | import java.util.HashSet; | ||||
| import java.util.List; | |||||
| /** | |||||
| * 语种服务 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-10-13 | |||||
| */ | |||||
| public interface VoiceLanguageMapper extends CommonMapper<VoiceLanguage, Long> { | public interface VoiceLanguageMapper extends CommonMapper<VoiceLanguage, Long> { | ||||
| void saveBatch(@Param("set") HashSet<VoiceLanguage> set); | void saveBatch(@Param("set") HashSet<VoiceLanguage> set); | ||||
| /** | |||||
| * 根据地区语言查询语种信息 | |||||
| * | |||||
| * @param local | |||||
| * @return {@link List}<{@link VoiceLanguage}> | |||||
| */ | |||||
| List<VoiceLanguage> listByLocal(@Param("local") String local); | |||||
| /** | |||||
| * 根据语言查询语种信息 | |||||
| * | |||||
| * @param language | |||||
| * @return {@link List}<{@link VoiceLanguage}> | |||||
| */ | |||||
| List<VoiceLanguage> listByLanguage(@Param("language") String language); | |||||
| } | } | ||||
| @@ -9,4 +9,5 @@ public interface VoiceLanguageService { | |||||
| List<VoiceLanguage> voiceTotal(); | List<VoiceLanguage> voiceTotal(); | ||||
| VoiceLanguage getLanguage(String paperwork); | |||||
| } | } | ||||
| @@ -3,14 +3,19 @@ package com.iformall.service.sm.impl; | |||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
| import com.iformall.constant.LanguageEnums; | |||||
| import com.iformall.domain.po.sm.VoiceLanguage; | import com.iformall.domain.po.sm.VoiceLanguage; | ||||
| import com.iformall.language.LanguageDetect; | |||||
| import com.iformall.mapper.VoiceLanguageMapper; | import com.iformall.mapper.VoiceLanguageMapper; | ||||
| import com.iformall.service.sm.VoiceLanguageService; | import com.iformall.service.sm.VoiceLanguageService; | ||||
| import com.iformall.util.DetectUtils; | |||||
| import org.apache.commons.collections.CollectionUtils; | import org.apache.commons.collections.CollectionUtils; | ||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Optional; | |||||
| @Service | @Service | ||||
| public class VoiceLanguageServiceImpl implements VoiceLanguageService { | public class VoiceLanguageServiceImpl implements VoiceLanguageService { | ||||
| @@ -23,4 +28,25 @@ public class VoiceLanguageServiceImpl implements VoiceLanguageService { | |||||
| List<VoiceLanguage> languages = voiceLanguageMapper.selectList(new LambdaQueryWrapper<VoiceLanguage>().eq(VoiceLanguage::getIsDel, 0).orderByAsc(VoiceLanguage::getLocal)); | List<VoiceLanguage> languages = voiceLanguageMapper.selectList(new LambdaQueryWrapper<VoiceLanguage>().eq(VoiceLanguage::getIsDel, 0).orderByAsc(VoiceLanguage::getLocal)); | ||||
| return CollectionUtils.isEmpty(languages) ? Lists.newArrayList() : languages; | return CollectionUtils.isEmpty(languages) ? Lists.newArrayList() : languages; | ||||
| } | } | ||||
| @Override | |||||
| public VoiceLanguage getLanguage(String paperwork) { | |||||
| // 文案中若包含指定语种,则规定为该语种 | |||||
| String detectLanguage = DetectUtils.detectLanguage(paperwork); | |||||
| detectLanguage = Optional.ofNullable(detectLanguage).orElseGet(() -> LanguageDetect.detect(paperwork)); | |||||
| detectLanguage = DetectUtils.getLocalLanguage(detectLanguage); | |||||
| List<VoiceLanguage> voiceLanguages; | |||||
| // 判断语种是否包含- | |||||
| String split = ".*-.*"; | |||||
| if (detectLanguage == null) { | |||||
| voiceLanguages = voiceLanguageMapper.listByLocal(LanguageEnums.en_US.getLocal()); | |||||
| } else if (detectLanguage.matches(split)) { | |||||
| voiceLanguages = voiceLanguageMapper.listByLocal(detectLanguage); | |||||
| } else { | |||||
| voiceLanguages = voiceLanguageMapper.listByLanguage(detectLanguage); | |||||
| } | |||||
| return voiceLanguages.get(0); | |||||
| } | |||||
| } | } | ||||
| @@ -1,6 +1,10 @@ | |||||
| <?xml version="1.0" encoding="utf-8" ?> | <?xml version="1.0" encoding="utf-8" ?> | ||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > | ||||
| <mapper namespace="com.iformall.mapper.VoiceLanguageMapper"> | <mapper namespace="com.iformall.mapper.VoiceLanguageMapper"> | ||||
| <sql id="allColumns"> | |||||
| `id`, `tenant_id`, `parent_tenant_id`, `language`, `country`, `local`, `name`, `chinese_name`, `img`, `create_date`, `update_date`, `is_del` | |||||
| </sql> | |||||
| <insert id="saveBatch" parameterType="java.util.HashSet"> | <insert id="saveBatch" parameterType="java.util.HashSet"> | ||||
| INSERT INTO voice_language (`id`, `country`, | INSERT INTO voice_language (`id`, `country`, | ||||
| `language`, `local`, `name`, `img`, `is_del`,`chinese_name`) | `language`, `local`, `name`, `img`, `is_del`,`chinese_name`) | ||||
| @@ -18,4 +22,22 @@ | |||||
| ) | ) | ||||
| </foreach> | </foreach> | ||||
| </insert> | </insert> | ||||
| <select id="listByLocal" resultType="com.iformall.domain.po.sm.VoiceLanguage"> | |||||
| SELECT | |||||
| <include refid="allColumns"/> | |||||
| FROM | |||||
| `voice_language` | |||||
| WHERE | |||||
| `is_del` = 0 AND | |||||
| LOWER( `local` ) = #{local} | |||||
| </select> | |||||
| <select id="listByLanguage" resultType="com.iformall.domain.po.sm.VoiceLanguage"> | |||||
| SELECT | |||||
| <include refid="allColumns"/> | |||||
| FROM | |||||
| `voice_language` | |||||
| WHERE | |||||
| `is_del` = 0 AND | |||||
| LOWER( `language` ) = #{language} | |||||
| </select> | |||||
| </mapper> | </mapper> | ||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.constant; | |||||
| /** | |||||
| * 地区语言列表(具体到地区语言) | |||||
| * 主要用来做默认语言常量 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-10-13 | |||||
| */ | |||||
| public enum LanguageEnums { | |||||
| en_US("en", "US", "en-US", "英语(美国)"), | |||||
| zh_CN("zh", "CN", "zh-CN", "中文(普通话,简体)"), | |||||
| ; | |||||
| LanguageEnums(String language, String country, String local, String desc) { | |||||
| this.language = language; | |||||
| this.country = country; | |||||
| this.local = local; | |||||
| this.desc = desc; | |||||
| } | |||||
| private String language; | |||||
| private String country; | |||||
| private String local; | |||||
| private String desc; | |||||
| public String getLanguage() { | |||||
| return language; | |||||
| } | |||||
| public String getCountry() { | |||||
| return country; | |||||
| } | |||||
| public String getLocal() { | |||||
| return local; | |||||
| } | |||||
| public String getDesc() { | |||||
| return desc; | |||||
| } | |||||
| public static LanguageEnums getEnum(String language) { | |||||
| for (LanguageEnums value : values()) { | |||||
| if (value.getLanguage().equals(language)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -1,105 +1,114 @@ | |||||
| package com.iformall.language; | package com.iformall.language; | ||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.cybozu.labs.langdetect.Detector; | import com.cybozu.labs.langdetect.Detector; | ||||
| import com.cybozu.labs.langdetect.DetectorFactory; | import com.cybozu.labs.langdetect.DetectorFactory; | ||||
| import com.cybozu.labs.langdetect.LangDetectException; | import com.cybozu.labs.langdetect.LangDetectException; | ||||
| import com.google.common.io.ByteStreams; | |||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import lombok.var; | |||||
| import org.apache.commons.io.IOUtils; | |||||
| import org.springframework.core.io.Resource; | import org.springframework.core.io.Resource; | ||||
| import org.springframework.core.io.support.PathMatchingResourcePatternResolver; | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; | ||||
| import org.springframework.util.StreamUtils; | |||||
| import sun.misc.IOUtils; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.nio.charset.StandardCharsets; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| @Slf4j | @Slf4j | ||||
| public class LanguageDetect { | public class LanguageDetect { | ||||
| private static Detector initDetector(){ | |||||
| private static Detector initDetector() { | |||||
| try { | try { | ||||
| // DetectorFactory.loadProfile(Thread.currentThread().getContextClassLoader().getResource("profiles").getPath()); | |||||
| // return DetectorFactory.create(); | |||||
| List<String> profile = new ArrayList<>(); | List<String> profile = new ArrayList<>(); | ||||
| try { | try { | ||||
| PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); | ||||
| Resource[] resources = resolver.getResources("classpath:profiles/*"); | Resource[] resources = resolver.getResources("classpath:profiles/*"); | ||||
| for (Resource resource:resources) { | |||||
| InputStream inputStream = resource.getInputStream(); | |||||
| // String str = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8); | |||||
| String str = new String(ByteStreams.toByteArray(inputStream)); | |||||
| profile.add(str); | |||||
| // InputStream inputStream = resource.getInputStream(); | |||||
| // byte[] bytes = new byte[(int) resource.contentLength()]; | |||||
| // inputStream.read(bytes); | |||||
| // profile.add(new String(bytes)); | |||||
| for (Resource resource : resources) { | |||||
| InputStream inputStream = resource.getInputStream(); | |||||
| String str = new String(IOUtils.toByteArray(inputStream)); | |||||
| profile.add(str); | |||||
| } | } | ||||
| } catch (IOException e) { | } catch (IOException e) { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| } | } | ||||
| if(!profile.isEmpty()){ | |||||
| if (!profile.isEmpty()) { | |||||
| DetectorFactory.clear(); | DetectorFactory.clear(); | ||||
| DetectorFactory.loadProfile(profile); | DetectorFactory.loadProfile(profile); | ||||
| return DetectorFactory.create(); | return DetectorFactory.create(); | ||||
| } | } | ||||
| } catch (LangDetectException e) { | } catch (LangDetectException e) { | ||||
| e.printStackTrace(); | e.printStackTrace(); | ||||
| log.error("语言检测初始化错误。"+e.getMessage()); | |||||
| log.error("语言检测初始化错误。" + e.getMessage()); | |||||
| } | } | ||||
| return null; | return null; | ||||
| } | } | ||||
| public static String detect(String str){ | |||||
| public static String detect(String str) { | |||||
| Detector detector = initDetector(); | Detector detector = initDetector(); | ||||
| if(detector == null){ | |||||
| if (detector == null) { | |||||
| return null; | return null; | ||||
| } | } | ||||
| detector.append(str); | detector.append(str); | ||||
| // try { | |||||
| // detect.getProbabilities(); | |||||
| // } catch (LangDetectException e) { | |||||
| // e.printStackTrace(); | |||||
| // } | |||||
| try { | try { | ||||
| String language = detector.detect(); | String language = detector.detect(); | ||||
| log.info("语种识别(" + str + ")-----" + language); | log.info("语种识别(" + str + ")-----" + language); | ||||
| return language; | return language; | ||||
| } catch (LangDetectException e) { | } catch (LangDetectException e) { | ||||
| e.printStackTrace(); | |||||
| log.error("语言检测错误。"); | |||||
| log.error("语言检测错误", e); | |||||
| } | } | ||||
| return null; | return null; | ||||
| } | } | ||||
| public static void main(String[] args) { | |||||
| // var resolver = new PathMatchingResourcePatternResolver(); | |||||
| // Resource[] resources = new Resource[0]; | |||||
| // try { | |||||
| // resources = resolver.getResources("classpath:profiles/*"); | |||||
| // } catch (IOException e) { | |||||
| // e.printStackTrace(); | |||||
| // } | |||||
| // for (var resource:resources) { | |||||
| // System.out.println(resource.getFilename()); | |||||
| // try { | |||||
| // byte[] bytes = new byte[0]; | |||||
| // bytes = new byte[resource.getInputStream().available()]; | |||||
| // resource.getInputStream().read(bytes); | |||||
| // String str = new String(bytes); | |||||
| // System.out.println(str); | |||||
| // } catch (IOException e) { | |||||
| // e.printStackTrace(); | |||||
| // } | |||||
| // | |||||
| // } | |||||
| private static void test() { | |||||
| // 测试用方法 | |||||
| PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); | |||||
| Resource[] resources = new Resource[0]; | |||||
| try { | |||||
| resources = resolver.getResources("classpath:profiles/*"); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| for (Resource resource : resources) { | |||||
| System.out.println(resource.getFilename()); | |||||
| try { | |||||
| byte[] bytes = new byte[0]; | |||||
| bytes = new byte[resource.getInputStream().available()]; | |||||
| resource.getInputStream().read(bytes); | |||||
| String str = new String(bytes); | |||||
| System.out.println(str); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| System.out.println(detect("科技公司")); | System.out.println(detect("科技公司")); | ||||
| System.out.println(detect("科技公司有哪几家做的还不错呢,其中就有我们这一家")); | |||||
| System.out.println(detect("中国科技还行吧")); | |||||
| System.out.println(detect("中国")); | |||||
| System.out.println(detect("梦想")); | |||||
| System.out.println(detect("I am a teacher")); | |||||
| System.out.println(detect("I am a 老师")); | |||||
| System.out.println(detect("行人從非機動車道變換車道到機動車道,激動的叫起來了")); | |||||
| System.out.println(detect("おはよう")); | |||||
| System.out.println("======================================="); | |||||
| String regex = ".*[\u4e00-\u9fa5]+.*"; | |||||
| // String regex2 = "\b.*[a-zA-Z]+.*\b"; | |||||
| String regex3 = ".*-.*"; | |||||
| System.out.println("I am a 老师".matches(regex)); | |||||
| System.out.println("I am a teacher".matches(regex)); | |||||
| System.out.println("I am a 我們".matches(regex)); | |||||
| System.out.println("行人從非機動車道變換車道到機動車道,激動的叫起來了".matches(regex)); | |||||
| System.out.println("======================================="); | |||||
| // System.out.println("I am a 老师".matches(regex2)); | |||||
| // System.out.println("I am a teacher".matches(regex2)); | |||||
| // System.out.println("abcdefg".matches(regex2)); | |||||
| // System.out.println("abc d e fg".matches(regex2)); | |||||
| System.out.println("======================================="); | |||||
| System.out.println("abc".matches(regex3)); | |||||
| System.out.println("a-bc".matches(regex3)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,45 @@ | |||||
| package com.iformall.util; | |||||
| import com.iformall.constant.LanguageEnums; | |||||
| import java.util.regex.Matcher; | |||||
| import java.util.regex.Pattern; | |||||
| /** | |||||
| * 语种检测类 | |||||
| * | |||||
| * @author xmzhao71 | |||||
| * @date 2023-10-13 | |||||
| */ | |||||
| public class DetectUtils { | |||||
| /** | |||||
| * 检测语言是否包含指定语种 | |||||
| * | |||||
| * @param text 文案 | |||||
| * @return {@link String} 指定地区语种 | |||||
| */ | |||||
| public static String detectLanguage(String text) { | |||||
| String zhCNRegex = ".*[\u4e00-\u9fa5]+.*"; | |||||
| if (text.matches(zhCNRegex)) { | |||||
| return LanguageEnums.zh_CN.getLocal(); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| /** | |||||
| * 获取地区语言 | |||||
| * | |||||
| * @param detectLanguage 检测语言 | |||||
| * @return {@link String} 指定地区语言 | |||||
| */ | |||||
| public static String getLocalLanguage(String detectLanguage) { | |||||
| if (detectLanguage == null) { | |||||
| return null; | |||||
| } | |||||
| if (detectLanguage.equalsIgnoreCase(LanguageEnums.en_US.getLanguage())) { | |||||
| return LanguageEnums.en_US.getLocal(); | |||||
| } | |||||
| return detectLanguage; | |||||
| } | |||||
| } | |||||