Commit cf09a778 authored by shj's avatar shj

[ADD] nuxt-i18n 추가, 인덱스 로드&관리 로컬라이제이션 적용

parent 9d294f2b
...@@ -27,15 +27,14 @@ public class GuideIndexController { ...@@ -27,15 +27,14 @@ public class GuideIndexController {
@ApiOperation(value="가이드 인덱스 전체 조회") @ApiOperation(value="가이드 인덱스 전체 조회")
@GetMapping("/all") @GetMapping("/all")
public ResponseEntity<?> getAll()throws Exception{ public ResponseEntity<?> getAll(@RequestParam(value = "locale", required = false) String locale)throws Exception{
return new ResponseEntity<>(service.getAll(), HttpStatus.OK); return new ResponseEntity<>(service.getAll(locale), HttpStatus.OK);
} }
@ApiOperation(value="가이드 인덱스 추가") @ApiOperation(value="가이드 인덱스 추가")
@PostMapping @PostMapping
public ResponseEntity<?> create(@RequestBody GuideIndex index) throws Exception{ public ResponseEntity<?> create(@RequestBody GuideIndex index) throws Exception{
return new ResponseEntity<>(service.create(index), HttpStatus.CREATED); return new ResponseEntity<>(service.create(index), HttpStatus.CREATED);
} }
@PutMapping @PutMapping
......
...@@ -11,9 +11,10 @@ import java.util.List; ...@@ -11,9 +11,10 @@ import java.util.List;
public interface GuideIndexRepository extends CrudRepository<GuideIndex, String> { public interface GuideIndexRepository extends CrudRepository<GuideIndex, String> {
List<GuideIndex> findAll(); List<GuideIndex> findAll();
List<GuideIndex> findAllByOrderByOrder(); List<GuideIndex> findAllByOrderByOrder();
List<GuideIndex> findAllByDepthOrderByOrder(Integer depth); List<GuideIndex> findAllByLocaleOrderByOrder(String locale);
List<GuideIndex> findAllByPathContainingAndDepth(String path, Integer depth); List<GuideIndex> findAllByDepthAndLocaleOrderByOrder(Integer depth, String locale);
List<GuideIndex> findAllByPathContainingAndDepthOrderByOrderDesc(String path, Integer depth); List<GuideIndex> findAllByPathContainingAndDepthAndLocale(String path, Integer depth, String locale);
GuideIndex findByPath(String path); List<GuideIndex> findAllByPathContainingAndDepthAndLocaleOrderByOrderDesc(String path, Integer depth, String locale);
GuideIndex findByPathContainingAndDepthAndOrder(String path, Integer depth, Integer order); GuideIndex findByPathAndLocale(String path, String locale);
GuideIndex findByPathContainingAndDepthAndOrderAndLocale(String path, Integer depth, Integer order, String locale);
} }
...@@ -41,12 +41,12 @@ public class GuideIndexService { ...@@ -41,12 +41,12 @@ public class GuideIndexService {
// order == 0 인 경우 부모 인덱스 반환 // order == 0 인 경우 부모 인덱스 반환
if(targetIndex.getOrder() == 0){ if(targetIndex.getOrder() == 0){
return repository.findByPath(parentPath); return repository.findByPathAndLocale(parentPath, targetIndex.getLocale());
} }
// 이전 형제의 자식이 없을 경우 해당 형제 반환 // 이전 형제의 자식이 없을 경우 해당 형제 반환
GuideIndex prevSibling = repository.findByPathContainingAndDepthAndOrder(parentPath, targetIndex.getDepth(), targetIndex.getOrder() - 1); GuideIndex prevSibling = repository.findByPathContainingAndDepthAndOrderAndLocale(parentPath, targetIndex.getDepth(), targetIndex.getOrder() - 1, targetIndex.getLocale());
if(repository.findAllByPathContainingAndDepth(prevSibling.getPath(), prevSibling.getDepth() + 1).size() == 0){ if(repository.findAllByPathContainingAndDepthAndLocale(prevSibling.getPath(), prevSibling.getDepth() + 1, prevSibling.getLocale()).size() == 0){
return prevSibling; return prevSibling;
} else { // 이전 형제의 자식이 있을 경우 가장 마지막 자식 반환 } else { // 이전 형제의 자식이 있을 경우 가장 마지막 자식 반환
return getLastChildIndex(prevSibling); return getLastChildIndex(prevSibling);
...@@ -54,9 +54,9 @@ public class GuideIndexService { ...@@ -54,9 +54,9 @@ public class GuideIndexService {
} }
public GuideIndex getLastChildIndex(GuideIndex targetIndex) throws Exception{ public GuideIndex getLastChildIndex(GuideIndex targetIndex) throws Exception{
GuideIndex lastChild = repository.findAllByPathContainingAndDepthOrderByOrderDesc(targetIndex.getPath(), targetIndex.getDepth() + 1).get(0); GuideIndex lastChild = repository.findAllByPathContainingAndDepthAndLocaleOrderByOrderDesc(targetIndex.getPath(), targetIndex.getDepth() + 1, targetIndex.getLocale()).get(0);
if(repository.findAllByPathContainingAndDepth(lastChild.getPath(), lastChild.getDepth() + 1).size() == 0){ if(repository.findAllByPathContainingAndDepthAndLocale(lastChild.getPath(), lastChild.getDepth() + 1, lastChild.getLocale()).size() == 0){
return lastChild; return lastChild;
} else { } else {
return getLastChildIndex(lastChild); return getLastChildIndex(lastChild);
...@@ -76,25 +76,29 @@ public class GuideIndexService { ...@@ -76,25 +76,29 @@ public class GuideIndexService {
// child가 있으면 order == 0 인 자식 반환 (onlySibling == true 일 경우 패스하여 형제 반환으로 넘어감) // child가 있으면 order == 0 인 자식 반환 (onlySibling == true 일 경우 패스하여 형제 반환으로 넘어감)
if(!onlySibling){ if(!onlySibling){
nextIndex = repository.findByPathContainingAndDepthAndOrder(path, targetIndex.getDepth() + 1, 0); nextIndex = repository.findByPathContainingAndDepthAndOrderAndLocale(path, targetIndex.getDepth() + 1, 0, targetIndex.getLocale());
} }
// child가 없으면 다음 형제 반환 // child가 없으면 다음 형제 반환
if(nextIndex == null){ if(nextIndex == null){
nextIndex = repository.findByPathContainingAndDepthAndOrder(parentPath, targetIndex.getDepth(), targetIndex.getOrder() + 1); nextIndex = repository.findByPathContainingAndDepthAndOrderAndLocale(parentPath, targetIndex.getDepth(), targetIndex.getOrder() + 1, targetIndex.getLocale());
} }
// child가 없고, 다음 형제 없는 경우, 부모 guide의 nextIndex 탐색 // child가 없고, 다음 형제 없는 경우, 부모 guide의 nextIndex 탐색
if(nextIndex == null && targetIndex.getDepth() != 1) { if(nextIndex == null && targetIndex.getDepth() != 1) {
GuideIndex parentIndex = repository.findByPath(parentPath); GuideIndex parentIndex = repository.findByPathAndLocale(parentPath, targetIndex.getLocale());
nextIndex = getNextIndex(parentIndex, true); nextIndex = getNextIndex(parentIndex, true);
} }
return nextIndex; return nextIndex;
} }
public List<GuideIndex> getAll() throws Exception{ public List<GuideIndex> getAll(String locale) throws Exception{
return repository.findAllByOrderByOrder(); if(locale == null){
return repository.findAllByOrderByOrder();
} else {
return repository.findAllByLocaleOrderByOrder(locale);
}
} }
@Transactional @Transactional
...@@ -141,7 +145,7 @@ public class GuideIndexService { ...@@ -141,7 +145,7 @@ public class GuideIndexService {
// 인덱스 증가해야 할 경우 (type == 1) // 인덱스 증가해야 할 경우 (type == 1)
if(type == 1){ if(type == 1){
if(targetIndex.getDepth() == 1){ if(targetIndex.getDepth() == 1){
List<GuideIndex> siblings = repository.findAllByDepthOrderByOrder(1); List<GuideIndex> siblings = repository.findAllByDepthAndLocaleOrderByOrder(1, targetIndex.getLocale());
siblings.forEach(el -> { siblings.forEach(el -> {
if(el.getOrder() >= targetIndex.getOrder()){ if(el.getOrder() >= targetIndex.getOrder()){
el.setOrder(el.getOrder() + 1); el.setOrder(el.getOrder() + 1);
...@@ -149,7 +153,7 @@ public class GuideIndexService { ...@@ -149,7 +153,7 @@ public class GuideIndexService {
} }
}); });
} else { } else {
List<GuideIndex> siblings = repository.findAllByPathContainingAndDepth(parentPath, targetIndex.getDepth()); List<GuideIndex> siblings = repository.findAllByPathContainingAndDepthAndLocale(parentPath, targetIndex.getDepth(), targetIndex.getLocale());
siblings.forEach(el -> { siblings.forEach(el -> {
if(el.getOrder() >= targetIndex.getOrder()){ if(el.getOrder() >= targetIndex.getOrder()){
el.setOrder(el.getOrder() + 1); el.setOrder(el.getOrder() + 1);
...@@ -164,7 +168,7 @@ public class GuideIndexService { ...@@ -164,7 +168,7 @@ public class GuideIndexService {
// 인덱스 감소해야 할 경우 (type == -1) // 인덱스 감소해야 할 경우 (type == -1)
if(type == -1){ if(type == -1){
if(targetIndex.getDepth() == 1){ if(targetIndex.getDepth() == 1){
List<GuideIndex> siblings = repository.findAllByDepthOrderByOrder(1); List<GuideIndex> siblings = repository.findAllByDepthAndLocaleOrderByOrder(1, targetIndex.getLocale());
siblings.forEach(el -> { siblings.forEach(el -> {
if(el.getOrder() > targetIndex.getOrder()){ if(el.getOrder() > targetIndex.getOrder()){
el.setOrder(el.getOrder() - 1); el.setOrder(el.getOrder() - 1);
...@@ -172,7 +176,7 @@ public class GuideIndexService { ...@@ -172,7 +176,7 @@ public class GuideIndexService {
} }
}); });
} else { } else {
List<GuideIndex> siblings = repository.findAllByPathContainingAndDepth(parentPath, targetIndex.getDepth()); List<GuideIndex> siblings = repository.findAllByPathContainingAndDepthAndLocale(parentPath, targetIndex.getDepth(), targetIndex.getLocale());
siblings.forEach(el -> { siblings.forEach(el -> {
if(el.getOrder() > targetIndex.getOrder()){ if(el.getOrder() > targetIndex.getOrder()){
el.setOrder(el.getOrder() - 1); el.setOrder(el.getOrder() - 1);
......
import ko from "./messages/ko.js";
import en from "./messages/en.js";
export default {
locale: "ko",
fallbackLocale: "ko",
messages: { ko, en },
};
export default [
{
code: "ko",
name: "Korean",
iso: "ko-KR",
},
{
code: "en",
name: "English",
iso: "en-US",
},
];
export default {
"서비스 가이드": "Service Guide",
"홈": "Home",
}
\ No newline at end of file
export default {
"서비스 가이드": "서비스 가이드",
"홈": "홈",
}
\ No newline at end of file
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
active-class="active" active-class="active"
:class="{active: $route.path === '/'}" :class="{active: $route.path === '/'}"
> >
<v-list-item-title></v-list-item-title> <v-list-item-title>{{$t('홈')}}</v-list-item-title>
</v-list-item> </v-list-item>
</v-list> </v-list>
...@@ -148,7 +148,11 @@ ...@@ -148,7 +148,11 @@
</div> </div>
</div> </div>
<v-icon @click="showSearch = !showSearch" class="header-icon">{{showSearch ? 'mdi-close' : 'mdi-magnify'}}</v-icon> <v-icon @click="showSearch = !showSearch" class="search-icon">{{showSearch ? 'mdi-close' : 'mdi-magnify'}}</v-icon>
<span @click="setLocale" class="locale-icon">
<span class="locale-icon__badge">{{$i18n.locale}}</span>
<v-icon class="ml-4 ">mdi-web</v-icon>
</span>
<v-app-bar-nav-icon class="mobile-show" v-if="!drawer" @click.stop="drawer = !drawer" /> <v-app-bar-nav-icon class="mobile-show" v-if="!drawer" @click.stop="drawer = !drawer" />
</v-row> </v-row>
...@@ -166,8 +170,15 @@ ...@@ -166,8 +170,15 @@
<v-row class="pa-10 pt-0 justify-space-around" no-gutters style="width: 100%; height: calc(100% - 68px);"> <v-row class="pa-10 pt-0 justify-space-around" no-gutters style="width: 100%; height: calc(100% - 68px);">
<v-col cols="5" style="height: 100%;"> <v-col cols="5" style="height: 100%; position: relative;">
<v-subheader>인덱스 목록</v-subheader> <v-subheader>
인덱스 목록
<v-spacer></v-spacer>
<span @click="setLocale" class="locale-icon">
<span class="locale-icon__badge">{{$i18n.locale}}</span>
<v-icon>mdi-web</v-icon>
</span>
</v-subheader>
<v-list v-if="editModeList && !loadingPageList"> <v-list v-if="editModeList && !loadingPageList">
<tree <tree
:items="editModeList" :items="editModeList"
...@@ -324,6 +335,9 @@ export default{ ...@@ -324,6 +335,9 @@ export default{
}, },
}, },
methods:{ methods:{
setLocale() {
this.$i18n.setLocale(this.$i18n.locale === 'ko' ? 'en' : 'ko')
},
openIndex() { openIndex() {
let route = this.$router.resolve({path: '/'}); let route = this.$router.resolve({path: '/'});
window.open(route.href, '_self'); window.open(route.href, '_self');
...@@ -337,11 +351,14 @@ export default{ ...@@ -337,11 +351,14 @@ export default{
this.selectedIndex = guide this.selectedIndex = guide
this.$router.push('/' + guide.id) this.$router.push('/' + guide.id)
}, },
async getGuideIndex(){ async getGuideIndex(){
this.loadingPageList = true this.loadingPageList = true
await this.$axios.get('/guide-index/all') await this.$axios.get('/guide-index/all', {
params:{
locale: this.$i18n.locale
}
})
.then(res => { .then(res => {
this.rawIndexList = res.data; this.rawIndexList = res.data;
this.getIndexTree(JSON.parse(JSON.stringify(res.data))); this.getIndexTree(JSON.parse(JSON.stringify(res.data)));
...@@ -494,7 +511,7 @@ export default{ ...@@ -494,7 +511,7 @@ export default{
const searchContainer = document.querySelector('.search-container') const searchContainer = document.querySelector('.search-container')
const searchInput = document.querySelector('.search-input') const searchInput = document.querySelector('.search-input')
const searchResult = document.querySelector('.search-result') const searchResult = document.querySelector('.search-result')
const searchBtn = document.querySelector('.header-icon') const searchBtn = document.querySelector('.search-icon')
const isClickInside = [searchContainer, searchInput, searchResult, searchBtn].some(item => const isClickInside = [searchContainer, searchInput, searchResult, searchBtn].some(item =>
item.contains(e.target) item.contains(e.target)
...@@ -565,6 +582,9 @@ export default{ ...@@ -565,6 +582,9 @@ export default{
}, },
watch:{ watch:{
'$i18n.locale'(val){
this.getGuideIndex()
},
'$store.state.guideNavigator'() { '$store.state.guideNavigator'() {
this.navPositionList = this.$store.state.guideNavigator.map((nav) => nav.position) this.navPositionList = this.$store.state.guideNavigator.map((nav) => nav.position)
}, },
...@@ -582,12 +602,28 @@ export default{ ...@@ -582,12 +602,28 @@ export default{
document.getElementsByTagName('html')[0].classList.remove('search-on') document.getElementsByTagName('html')[0].classList.remove('search-on')
window.removeEventListener('click', this.clickOutsideEvent); window.removeEventListener('click', this.clickOutsideEvent);
} }
} },
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.app-bar-wrap, .edit-dialog-container {
.locale-icon {
position: relative;
cursor: pointer;
.locale-icon__badge {
position: absolute;
right: 20px;
top: -6px;
font-size: 0.75rem;
text-transform: uppercase;
font-weight: 700;
}
}
}
.v-dialog { .v-dialog {
width: 70vw !important; width: 70vw !important;
height: 80vh; height: 80vh;
...@@ -669,7 +705,7 @@ html.search-on { ...@@ -669,7 +705,7 @@ html.search-on {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
top: 48px; top: 48px;
right: 96px; right: 136px;
border: 1px solid rgb(238, 238, 238); border: 1px solid rgb(238, 238, 238);
border-top: none; border-top: none;
border-radius: 0 0 28px 28px; border-radius: 0 0 28px 28px;
...@@ -698,7 +734,7 @@ html.search-on { ...@@ -698,7 +734,7 @@ html.search-on {
@media screen and (min-width: 1264px) { @media screen and (min-width: 1264px) {
.search-result { .search-result {
right: 48px; right: 88px;
} }
} }
......
import colors from 'vuetify/es5/util/colors' import colors from 'vuetify/es5/util/colors'
import i18nConfig from "./i18n/config";
import locales from "./i18n/locales";
export default { export default {
...@@ -57,8 +58,17 @@ export default { ...@@ -57,8 +58,17 @@ export default {
// Modules: https://go.nuxtjs.dev/config-modules // Modules: https://go.nuxtjs.dev/config-modules
modules: [ modules: [
'nuxt-healthcheck', 'nuxt-healthcheck',
'@nuxtjs/markdownit' '@nuxtjs/markdownit',
'nuxt-i18n',
], ],
i18n:{
seo: true,
locales,
defaultLocale: 'ko',
vueI18n: i18nConfig,
skipSettingLocaleOnNavigate: true,
},
// Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
vuetify: { vuetify: {
......
This diff is collapsed.
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
"markdown-it-div": "^1.1.0", "markdown-it-div": "^1.1.0",
"nuxt": "^2.15.8", "nuxt": "^2.15.8",
"nuxt-healthcheck": "^1.0.1", "nuxt-healthcheck": "^1.0.1",
"nuxt-i18n": "^6.28.1",
"sass-loader": "^10.2.0", "sass-loader": "^10.2.0",
"vue": "^2.7.10", "vue": "^2.7.10",
"vue-no-ssr": "^1.1.1", "vue-no-ssr": "^1.1.1",
......
...@@ -171,8 +171,8 @@ export default { ...@@ -171,8 +171,8 @@ export default {
async getGuideContents() { async getGuideContents() {
const contentKey = `${this.guide.path.substring(0,this.guide.path.length-1)}.md` const contentKey = `${this.guide.path.substring(0,this.guide.path.length-1)}.md`
await this.$axios.get(
await this.$axios.get("https://api.github.com/repos/vazilcompany/vridge-docs/contents/guide/ko/" + contentKey, { `https://api.github.com/repos/vazilcompany/vridge-docs/contents/guide/${this.$i18n.locale}/` + contentKey, {
headers:{ headers:{
Authorization: 'token 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' Authorization: 'token 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'
} }
...@@ -183,24 +183,10 @@ export default { ...@@ -183,24 +183,10 @@ export default {
}) })
.catch(err=>{ .catch(err=>{
this.guide.content = '' this.guide.content = ''
console.log(err) console.log('가이드 로드 실패')
}) })
}, },
parsingContentTitle(content) {
let keyArray = content.contentKey.replace('.md','').split('/')
let titleKey = ''
if(keyArray[0] !== keyArray[1]) {
for(let i = 0; i < keyArray.length - 1; i++) {
titleKey += keyArray[i] + '_'
}
titleKey += content.title
} else {
titleKey = content.title
}
return titleKey
},
getBreadcrumbs(){ getBreadcrumbs(){
let items = [] let items = []
let paths = this.guide.path.substring(0, this.guide.path.length-1).split('/') let paths = this.guide.path.substring(0, this.guide.path.length-1).split('/')
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="guide-wrap-container"> <div class="guide-wrap-container">
<v-container class="guide-wrap"> <v-container class="guide-wrap">
<v-row no-gutters align="center" justify="center" class="guide-wrap-header"> <v-row no-gutters align="center" justify="center" class="guide-wrap-header">
<h1 class="font-weight-bold">서비스 가이드</h1> <h1 class="font-weight-bold">{{$t('서비스 가이드')}}</h1>
</v-row> </v-row>
<v-row no-gutters class="guide-content"> <v-row no-gutters class="guide-content">
...@@ -29,7 +29,11 @@ export default { ...@@ -29,7 +29,11 @@ export default {
}), }),
methods:{ methods:{
async getGuideIndex(){ async getGuideIndex(){
await this.$axios.get('http://localhost:5000/guide-index/all') await this.$axios.get('/guide-index/all', {
params:{
locale: this.$i18n.locale
}
})
.then(res => { .then(res => {
this.getIndexTree(JSON.parse(JSON.stringify(res.data))); this.getIndexTree(JSON.parse(JSON.stringify(res.data)));
}) })
...@@ -77,6 +81,9 @@ export default { ...@@ -77,6 +81,9 @@ export default {
this.getGuideIndex() this.getGuideIndex()
}, },
watch:{ watch:{
'$i18n.locale'(){
this.getGuideIndex()
}
} }
} }
</script> </script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment