@@ -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 | |||
*.iws | |||
*.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("************************异常开始*******************************"); | |||
if(checkExceptionType(ex)) { | |||
// 特殊异常不打印堆栈 | |||
logger.error(ex.getMessage()); | |||
logger.error("message:" + ex); | |||
logger.error("************************异常结束*******************************"); | |||
return; | |||
} | |||
logger.error("请求地址:" + request.getRequestURL()); | |||
logger.error("message:"+ ex.getMessage()); | |||
logger.error("message:"+ ex); | |||
Enumeration enumeration = request.getParameterNames(); | |||
logger.error("请求参数"); | |||
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 java.util.HashSet; | |||
import java.util.List; | |||
/** | |||
* 语种服务 | |||
* | |||
* @author xmzhao71 | |||
* @date 2023-10-13 | |||
*/ | |||
public interface VoiceLanguageMapper extends CommonMapper<VoiceLanguage, Long> { | |||
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(); | |||
VoiceLanguage getLanguage(String paperwork); | |||
} |
@@ -3,14 +3,19 @@ package com.iformall.service.sm.impl; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.google.common.collect.Lists; | |||
import com.iformall.constant.LanguageEnums; | |||
import com.iformall.domain.po.sm.VoiceLanguage; | |||
import com.iformall.language.LanguageDetect; | |||
import com.iformall.mapper.VoiceLanguageMapper; | |||
import com.iformall.service.sm.VoiceLanguageService; | |||
import com.iformall.util.DetectUtils; | |||
import org.apache.commons.collections.CollectionUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
import org.springframework.stereotype.Service; | |||
import java.util.List; | |||
import java.util.Optional; | |||
@Service | |||
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)); | |||
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" ?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > | |||
<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 INTO voice_language (`id`, `country`, | |||
`language`, `local`, `name`, `img`, `is_del`,`chinese_name`) | |||
@@ -18,4 +22,22 @@ | |||
) | |||
</foreach> | |||
</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> |
@@ -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; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.cybozu.labs.langdetect.Detector; | |||
import com.cybozu.labs.langdetect.DetectorFactory; | |||
import com.cybozu.labs.langdetect.LangDetectException; | |||
import com.google.common.io.ByteStreams; | |||
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.support.PathMatchingResourcePatternResolver; | |||
import org.springframework.util.StreamUtils; | |||
import sun.misc.IOUtils; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
@Slf4j | |||
public class LanguageDetect { | |||
private static Detector initDetector(){ | |||
private static Detector initDetector() { | |||
try { | |||
// DetectorFactory.loadProfile(Thread.currentThread().getContextClassLoader().getResource("profiles").getPath()); | |||
// return DetectorFactory.create(); | |||
List<String> profile = new ArrayList<>(); | |||
try { | |||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); | |||
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) { | |||
e.printStackTrace(); | |||
} | |||
if(!profile.isEmpty()){ | |||
if (!profile.isEmpty()) { | |||
DetectorFactory.clear(); | |||
DetectorFactory.loadProfile(profile); | |||
return DetectorFactory.create(); | |||
} | |||
} catch (LangDetectException e) { | |||
e.printStackTrace(); | |||
log.error("语言检测初始化错误。"+e.getMessage()); | |||
log.error("语言检测初始化错误。" + e.getMessage()); | |||
} | |||
return null; | |||
} | |||
public static String detect(String str){ | |||
public static String detect(String str) { | |||
Detector detector = initDetector(); | |||
if(detector == null){ | |||
if (detector == null) { | |||
return null; | |||
} | |||
detector.append(str); | |||
// try { | |||
// detect.getProbabilities(); | |||
// } catch (LangDetectException e) { | |||
// e.printStackTrace(); | |||
// } | |||
try { | |||
String language = detector.detect(); | |||
log.info("语种识别(" + str + ")-----" + language); | |||
return language; | |||
} catch (LangDetectException e) { | |||
e.printStackTrace(); | |||
log.error("语言检测错误。"); | |||
log.error("语言检测错误", e); | |||
} | |||
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("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; | |||
} | |||
} |