Add header profile drawer

This commit is contained in:
mashirozx 2021-08-08 17:10:19 +08:00
parent ebf33e97fe
commit a77e7a49bc
8 changed files with 308 additions and 53 deletions

View File

@ -5,7 +5,7 @@
define('SAKURA_VERSION', wp_get_theme()->get('Version')); define('SAKURA_VERSION', wp_get_theme()->get('Version'));
define('SAKURA_TEXT_DOMAIN', wp_get_theme()->get('TextDomain')); define('SAKURA_TEXT_DOMAIN', wp_get_theme()->get('TextDomain'));
define('SAKURA_DEVEPLOMENT', false); define('SAKURA_DEVEPLOMENT', true);
define('SAKURA_DEVEPLOMENT_HOST', 'http://127.0.0.1:9000'); define('SAKURA_DEVEPLOMENT_HOST', 'http://127.0.0.1:9000');
// PHP loaders // PHP loaders

View File

@ -8,14 +8,18 @@
:alt="$props.data.title" :alt="$props.data.title"
placeholder="https://via.placeholder.com/1024x768" placeholder="https://via.placeholder.com/1024x768"
:draggable="false" :draggable="false"
:ratio="9 / 16"
/> />
</Link> </Link>
</div> </div>
<div class="row__wrapper--title"> <div class="row__wrapper--date">
<span><i class="far fa-clock"></i> {{ $props.data.publistTime }}</span>
</div>
<h3 class="row__wrapper--title">
<Link :url="$props.data.link"> <Link :url="$props.data.link">
<span>{{ $props.data.title }}</span> <span>{{ $props.data.title }}</span>
</Link> </Link>
</div> </h3>
<div class="row__wrapper--statistics"> <div class="row__wrapper--statistics">
<div class="column__wrapper--read_count"> <div class="column__wrapper--read_count">
<span><i class="fab fa-hotjar"></i> {{ $props.data.readCount }}</span> <span><i class="fab fa-hotjar"></i> {{ $props.data.readCount }}</span>
@ -82,11 +86,21 @@ export default defineComponent({
user-select: none; user-select: none;
@include polyfills.flex-gap(12px, 'column nowrap'); @include polyfills.flex-gap(12px, 'column nowrap');
> * { > * {
width: calc(100% - 24px); width: calc(100% - 48px);
} }
> .row__wrapper { > .row__wrapper {
&--thumbnail { &--thumbnail {
width: 100%; width: calc(100% - 24px);
border-radius: 10px;
overflow: hidden;
.image {
object-fit: cover;
transform: scale(1);
transition: transform 0.3s ease-in-out;
&:hover {
transform: scale(1.1);
}
}
} }
&--tags { &--tags {
max-height: 32px; max-height: 32px;
@ -106,6 +120,10 @@ export default defineComponent({
} }
} }
} }
&--date {
color: #888888;
font-size: 12px;
}
&--title { &--title {
line-height: 30px; line-height: 30px;
font-size: x-large; // 24 font-size: x-large; // 24

View File

@ -82,9 +82,9 @@
</template> </template>
</Switcher> </Switcher>
</div> </div>
<div class="option inform" v-tippy="{ content: messages.privacy.email.title }"> <div class="option subscribe" v-tippy="{ content: messages.privacy.subscribe.title }">
<Switcher <Switcher
v-model:checked="privacyShouldInform" v-model:checked="privacyIsSubscribe"
positiveLabel="" positiveLabel=""
negativeLabel="" negativeLabel=""
:disableRipple="true" :disableRipple="true"
@ -92,13 +92,13 @@
<template #label-positive> <template #label-positive>
<span> <span>
<i class="fas fa-bell"></i> <i class="fas fa-bell"></i>
{{ messages.privacy.email.positive }} {{ messages.privacy.subscribe.positive }}
</span> </span>
</template> </template>
<template #label-negative> <template #label-negative>
<span> <span>
<i class="fas fa-bell-slash"></i> <i class="fas fa-bell-slash"></i>
{{ messages.privacy.email.negative }} {{ messages.privacy.subscribe.negative }}
</span> </span>
</template> </template>
</Switcher> </Switcher>
@ -174,10 +174,6 @@ export default defineComponent({
setup(props, { emit }) { setup(props, { emit }) {
const intl = useIntl() const intl = useIntl()
const messages = { const messages = {
markdownTips: intl.formatMessage({
id: 'posts.comment.composer.tips.markdownSupported',
defaultMessage: 'Markdown Supported',
}),
textareaLabel: intl.formatMessage({ textareaLabel: intl.formatMessage({
id: 'posts.comment.composer.content.label', id: 'posts.comment.composer.content.label',
defaultMessage: 'You are a surprise that I will only meet once in my life', defaultMessage: 'You are a surprise that I will only meet once in my life',
@ -216,7 +212,7 @@ export default defineComponent({
defaultMessage: 'Privacy settings', defaultMessage: 'Privacy settings',
}), }),
markdownTooltip: intl.formatMessage({ markdownTooltip: intl.formatMessage({
id: 'posts.comment.composer.toolkits.preview.tooltip', id: 'posts.comment.composer.toolkits.markdown.tooltip',
defaultMessage: defaultMessage:
'\'<a href="https://guides.github.com/features/mastering-markdown/" target="_blank">Markdown</a>\' supported', '\'<a href="https://guides.github.com/features/mastering-markdown/" target="_blank">Markdown</a>\' supported',
}), }),
@ -243,25 +239,25 @@ export default defineComponent({
'Whether to create secret comment that only admins and peoples mentioned can see?', 'Whether to create secret comment that only admins and peoples mentioned can see?',
}), }),
positive: intl.formatMessage({ positive: intl.formatMessage({
id: 'posts.comment.composer.privacy.anynomous.positive', id: 'posts.comment.composer.privacy.visibility.positive',
defaultMessage: 'Secret', defaultMessage: 'Secret',
}), }),
negative: intl.formatMessage({ negative: intl.formatMessage({
id: 'posts.comment.composer.privacy.anynomous.negative', id: 'posts.comment.composer.privacy.visibility.negative',
defaultMessage: 'Public', defaultMessage: 'Public',
}), }),
}, },
email: { subscribe: {
title: intl.formatMessage({ title: intl.formatMessage({
id: 'posts.comment.composer.privacy.email.title', id: 'posts.comment.composer.privacy.subscribe.title',
defaultMessage: 'Whether to inform you with email when receiving reply?', defaultMessage: 'Whether to inform you with email when receiving reply?',
}), }),
positive: intl.formatMessage({ positive: intl.formatMessage({
id: 'posts.comment.composer.privacy.email.positive', id: 'posts.comment.composer.privacy.subscribe.positive',
defaultMessage: 'Subscribe', defaultMessage: 'Subscribe',
}), }),
negative: intl.formatMessage({ negative: intl.formatMessage({
id: 'posts.comment.composer.privacy.email.negative', id: 'posts.comment.composer.privacy.subscribe.negative',
defaultMessage: 'Unsubscribe', defaultMessage: 'Unsubscribe',
}), }),
}, },
@ -275,7 +271,7 @@ export default defineComponent({
const privacyIsPrivate = ref(false) const privacyIsPrivate = ref(false)
const privacyIsAnynomous = ref(false) const privacyIsAnynomous = ref(false)
const privacyShouldInform = ref(true) const privacyIsSubscribe = ref(true)
// TODO: debounce // TODO: debounce
const handleSubmitEvent = () => { const handleSubmitEvent = () => {
@ -365,7 +361,7 @@ export default defineComponent({
handleTogglePrivacyOptionsEvent, handleTogglePrivacyOptionsEvent,
privacyIsPrivate, privacyIsPrivate,
privacyIsAnynomous, privacyIsAnynomous,
privacyShouldInform, privacyIsSubscribe,
} }
}, },
}) })

View File

@ -1,5 +1,5 @@
<template> <template>
<div :class="['image__container', state]"> <div :class="['image__container', state]" :ref="setContainerRef" :style="{ height: imageHeight }">
<img <img
:class="['image', state]" :class="['image', state]"
:src="$props.src" :src="$props.src"
@ -20,7 +20,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, computed } from 'vue' import { defineComponent, computed } from 'vue'
import { useState } from '@/hooks' import { useState, useResizeObserver, useElementRef } from '@/hooks'
import gravatar from '@/utils/gravatar' import gravatar from '@/utils/gravatar'
export default defineComponent({ export default defineComponent({
@ -31,6 +31,7 @@ export default defineComponent({
avatar: { type: Boolean, default: false }, avatar: { type: Boolean, default: false },
alt: String, alt: String,
draggable: { type: Boolean, default: false }, draggable: { type: Boolean, default: false },
ratio: { type: Number, default: NaN },
}, },
setup(props, { emit }) { setup(props, { emit }) {
const [state, setState] = useState('loading') const [state, setState] = useState('loading')
@ -53,11 +54,24 @@ export default defineComponent({
emit('load', event) emit('load', event)
} }
const [containerRef, setContainerRef] = useElementRef()
const containerSize = useResizeObserver(containerRef)
const imageHeight = computed(() => {
if (!isNaN(props.ratio) && props.ratio >= 0) {
return `${containerSize.value.width * props.ratio}px`
} else {
return '100%'
}
})
return { return {
placeholderImage, placeholderImage,
handleError, handleError,
handleLoad, handleLoad,
state, state,
setContainerRef,
imageHeight,
} }
}, },
}) })

View File

@ -5,9 +5,12 @@
<router-link v-else-if="to" :to="to"> <router-link v-else-if="to" :to="to">
<slot></slot> <slot></slot>
</router-link> </router-link>
<a v-else href="https://google.com" target="_blank"> <a v-else-if="hyperlink" href="hyperlink" target="_blank">
<slot></slot> <slot></slot>
</a> </a>
<span v-else>
<slot></slot>
</span>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -46,7 +49,15 @@ export default defineComponent({
} }
}) })
return { to } const hyperlink = computed(() => {
if (props.url === '' || props.url === '#') {
return false
} else {
return props.url
}
})
return { to, hyperlink }
}, },
}) })
</script> </script>

View File

@ -2,6 +2,9 @@
<div class="header__container mdc-elevation--z4"> <div class="header__container mdc-elevation--z4">
<div class="header__content"> <div class="header__content">
<div class="logo__wrapper"> <div class="logo__wrapper">
<Ripple>
<Link :to="{ name: 'Home' }">
<div class="logo__container">
<img <img
class="logo" class="logo"
:src="logo" :src="logo"
@ -10,6 +13,9 @@
@load="computeShouldHideNavItemList" @load="computeShouldHideNavItemList"
/> />
</div> </div>
</Link>
</Ripple>
</div>
<div class="nav__wrapper" :ref="setNavBarWrapperRef" @resize="handleNavBarWrapperResizeEvent"> <div class="nav__wrapper" :ref="setNavBarWrapperRef" @resize="handleNavBarWrapperResizeEvent">
<div class="nav__ul nav__ul--parent" :ref="setNavBarItemRefs"> <div class="nav__ul nav__ul--parent" :ref="setNavBarItemRefs">
<div <div
@ -67,8 +73,33 @@
</div> </div>
</div> </div>
<div class="profile__wrapper"> <div class="profile__wrapper">
<Ripple>
<div class="image__wrapper">
<img class="avatar" :src="avatar" alt="avatar" /> <img class="avatar" :src="avatar" alt="avatar" />
</div> </div>
</Ripple>
<div class="drop-down__wrapper">
<div class="ul mdc-elevation--z8">
<div class="content-logined" v-if="logined">logined</div>
<div class="content-unsigned" v-else>unsigned</div>
<div class="li" v-for="(item, index) in languageOptions" :key="index">
<NavItem :context="item.title" :prefix="item.icon" :url="item.url"></NavItem>
<div class="child__ul language mdc-elevation--z8" v-if="item.child.length > 0">
<div class="child__li" v-for="(child, childIndex) in item.child" :key="childIndex">
<NavItem :context="child.title" :prefix="child.icon" :url="child.url"></NavItem>
</div>
</div>
</div>
<div
class="li"
v-for="(item, index) in logined ? loginedOptions : unsignedOptions"
:key="index"
>
<NavItem :context="item.title" :prefix="item.icon" :url="item.url"></NavItem>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -87,9 +118,10 @@ import { init } from '@/store'
import sakuraOptions from '@/utils/sakuraOptions' import sakuraOptions from '@/utils/sakuraOptions'
import camelcaseKeys from 'camelcase-keys' import camelcaseKeys from 'camelcase-keys'
import NavItem from '@/layouts/components/header/NavItem.vue' import NavItem from '@/layouts/components/header/NavItem.vue'
import Ripple from '@/components/ripple/Ripple.vue'
export default defineComponent({ export default defineComponent({
components: { NavItem }, components: { NavItem, Ripple },
setup() { setup() {
const avatar = 'https://view.moezx.cc/images/2021/06/13/d6b010a378d392d4633008b915f98ab1.md.png' const avatar = 'https://view.moezx.cc/images/2021/06/13/d6b010a378d392d4633008b915f98ab1.md.png'
const logo = sakuraOptions['basic.site.logo'][0]?.url || 'https://v3.vuejs.org/logo.png' const logo = sakuraOptions['basic.site.logo'][0]?.url || 'https://v3.vuejs.org/logo.png'
@ -142,6 +174,33 @@ export default defineComponent({
return items return items
}) })
const unsignedOptions = [
{ title: 'Register', icon: 'fas fa-user-plus', url: '' },
{ title: 'Sign in', icon: 'fas fa-sign-out-alt', url: '' },
]
const loginedOptions = [
{ title: 'User Center', icon: 'fas fa-user', url: '' },
{ title: 'Sign out', icon: 'fas fa-sign-out-alt', url: '' },
]
const languageOptions = [
{
title: 'Language',
icon: 'fas fa-globe',
url: '',
child: [
{ title: '简体中文', value: 'zh-CN' },
{ title: '繁體中文', value: 'zh-HK' },
{ title: 'English', value: 'en' },
{ title: 'Español', value: 'es' },
{ title: 'Deutsch', value: 'de' },
{ title: 'Français', value: 'fr' },
{ title: 'Русский', value: 'ru' },
{ title: '日本語', value: 'ja' },
],
},
]
const logined = ref(true)
return { return {
navItems, navItems,
setNavBarWrapperRef, setNavBarWrapperRef,
@ -153,6 +212,10 @@ export default defineComponent({
logo, logo,
initState, initState,
useMDCRipple, useMDCRipple,
logined,
loginedOptions,
unsignedOptions,
languageOptions,
} }
}, },
}) })
@ -168,17 +231,23 @@ export default defineComponent({
align-items: center; align-items: center;
background: #ffffff; background: #ffffff;
> .header__content { > .header__content {
width: calc(100% - 48px); // width: calc(100% - 48px);
width: 100%;
height: 48px; height: 48px;
display: flex; display: flex;
flex-flow: row nowrap; flex-flow: row nowrap;
> .logo__wrapper { > .logo__wrapper {
flex: 0 0 auto; flex: 0 0 auto;
height: 100%;
.logo__container {
height: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
> .logo { .logo {
height: 32px; height: 32px;
padding: 0 24px;
}
} }
} }
> .nav__wrapper { > .nav__wrapper {
@ -186,7 +255,7 @@ export default defineComponent({
width: 100%; width: 100%;
display: flex; display: flex;
flex-flow: row nowrap; flex-flow: row nowrap;
padding: 0 24px; // padding: 0 24px;
.nav__ul { .nav__ul {
&.hide { &.hide {
position: absolute; position: absolute;
@ -309,9 +378,14 @@ export default defineComponent({
> .profile__wrapper { > .profile__wrapper {
flex: 0 0 auto; flex: 0 0 auto;
height: 100%;
position: relative;
.image__wrapper {
height: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 0 24px;
> .avatar { > .avatar {
height: 32px; height: 32px;
width: 32px; width: 32px;
@ -319,6 +393,72 @@ export default defineComponent({
border-radius: 50%; border-radius: 50%;
} }
} }
.drop-down__wrapper {
position: absolute;
top: 48px;
right: 0;
width: auto;
z-index: -1;
pointer-events: none;
visibility: hidden;
transform: translate(0, -100%);
// pointer-events: all;
// cursor: pointer;
// visibility: visible;
// transform: translate(0, 0%);
transition: all 0.2s ease-in-out;
.ul {
position: relative;
padding: 16px 0;
background: #ffffff;
border-radius: 0 0 5px 5px;
> .li {
height: 48px;
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
position: relative;
> .child__ul {
position: absolute;
top: 0;
left: 0;
z-index: -1;
padding: 16px 0;
transform: translate(-100%, -16px) scale(0, 0);
transform-origin: right (16px + math.div(48px, 2));
background: #ffffff;
border-radius: 5px;
width: auto;
transition: all 0.2s ease-in-out;
> .child__li {
height: 48px;
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
}
}
&:hover {
> .child__ul {
transform: translate(-100%, -16px) scale(1, 1);
}
}
}
}
::v-deep() {
.link__container .nav-item__container .nav-item__content {
justify-content: flex-start;
}
}
}
&:hover .drop-down__wrapper {
pointer-events: all;
cursor: pointer;
visibility: visible;
transform: translate(0, 0%);
}
}
} }
} }
</style> </style>

View File

@ -10,7 +10,13 @@
"messages.admin.uplicateUrls": "Duplicate URLs", "messages.admin.uplicateUrls": "Duplicate URLs",
"messages.comment.submit.error": "Comment post failure.", "messages.comment.submit.error": "Comment post failure.",
"messages.comment.submit.success": "Comment post successfully.", "messages.comment.submit.success": "Comment post successfully.",
"messages.commentList.cache.updateError": "Opps! Something went wrong when updating comment list.",
"messages.commentList.cache.updateSuccess": "Comment list updated.",
"messages.commentList.cache.updating": "Updating the latest comment list...",
"messages.commentList.title.commentCount": "{commentCount, plural, =0 {Be the first one to leave a comment!} =1 {One comment} other {{commentCount, number, ::compact-short} Comments}}",
"messages.commentList.title.heading": "Comments",
"messages.commonMessages.javascriptErrorTitle": "Opps, something when wrong!", "messages.commonMessages.javascriptErrorTitle": "Opps, something when wrong!",
"messages.content.status.errorLoadingComponent": "Something went wrong when loading this component.",
"messages.popup.close": "Close", "messages.popup.close": "Close",
"messages.popup.dismiss": "Dismiss", "messages.popup.dismiss": "Dismiss",
"messages.popup.showDetails": "Show details", "messages.popup.showDetails": "Show details",
@ -69,8 +75,21 @@
"posts.comment.composer.authorUrl.label": "Link", "posts.comment.composer.authorUrl.label": "Link",
"posts.comment.composer.captcha.toggleButton": "Captcha", "posts.comment.composer.captcha.toggleButton": "Captcha",
"posts.comment.composer.content.label": "You are a surprise that I will only meet once in my life", "posts.comment.composer.content.label": "You are a surprise that I will only meet once in my life",
"posts.comment.composer.privacy.anynomous.negative": "Autonym",
"posts.comment.composer.privacy.anynomous.positive": "Anynomous",
"posts.comment.composer.privacy.anynomous.title": "Whether to comment as an anynomous user?",
"posts.comment.composer.privacy.subscribe.negative": "Unsubscribe",
"posts.comment.composer.privacy.subscribe.positive": "Subscribe",
"posts.comment.composer.privacy.subscribe.title": "Whether to inform you with email when receiving reply?",
"posts.comment.composer.privacy.visibility.negative": "Public",
"posts.comment.composer.privacy.visibility.positive": "Secret",
"posts.comment.composer.privacy.visibility.title": "Whether to create secret comment that only admins and peoples mentioned can see?",
"posts.comment.composer.submit.button": "Submit", "posts.comment.composer.submit.button": "Submit",
"posts.comment.composer.tips.markdownSupported": "Markdown Supported", "posts.comment.composer.toolkits.emoji.tooltip": "Insert emoji",
"posts.comment.composer.toolkits.image.tooltip": "Attach image",
"posts.comment.composer.toolkits.markdown.tooltip": "'<a href=\"https://guides.github.com/features/mastering-markdown/\" target=\"_blank\">Markdown</a>' supported",
"posts.comment.composer.toolkits.preview.tooltip": "'<i class=\"fab fa-markdown\"></i>' Markdown preview",
"posts.comment.composer.toolkits.privacy.tooltip": "Privacy settings",
"posts.commentCount": "{commentCount, plural, =0 {No comment} =1 {One comment} other {{commentCount, number, ::compact-short} Comments}}", "posts.commentCount": "{commentCount, plural, =0 {No comment} =1 {One comment} other {{commentCount, number, ::compact-short} Comments}}",
"posts.postTimeOn.brief": "{publistTimeDate, date, long}", "posts.postTimeOn.brief": "{publistTimeDate, date, long}",
"posts.postTimeOn.full": "Post on {publistTimeDate, date, long}", "posts.postTimeOn.full": "Post on {publistTimeDate, date, long}",

View File

@ -32,9 +32,27 @@
"messages.comment.submit.success": { "messages.comment.submit.success": {
"defaultMessage": "Comment post successfully." "defaultMessage": "Comment post successfully."
}, },
"messages.commentList.cache.updateError": {
"defaultMessage": "Opps! Something went wrong when updating comment list."
},
"messages.commentList.cache.updateSuccess": {
"defaultMessage": "Comment list updated."
},
"messages.commentList.cache.updating": {
"defaultMessage": "Updating the latest comment list..."
},
"messages.commentList.title.commentCount": {
"defaultMessage": "{commentCount, plural, =0 {Be the first one to leave a comment!} =1 {One comment} other {{commentCount, number, ::compact-short} Comments}}"
},
"messages.commentList.title.heading": {
"defaultMessage": "Comments"
},
"messages.commonMessages.javascriptErrorTitle": { "messages.commonMessages.javascriptErrorTitle": {
"defaultMessage": "Opps, something when wrong!" "defaultMessage": "Opps, something when wrong!"
}, },
"messages.content.status.errorLoadingComponent": {
"defaultMessage": "Something went wrong when loading this component."
},
"messages.popup.close": { "messages.popup.close": {
"defaultMessage": "Close" "defaultMessage": "Close"
}, },
@ -209,11 +227,50 @@
"posts.comment.composer.content.label": { "posts.comment.composer.content.label": {
"defaultMessage": "You are a surprise that I will only meet once in my life" "defaultMessage": "You are a surprise that I will only meet once in my life"
}, },
"posts.comment.composer.privacy.anynomous.negative": {
"defaultMessage": "Autonym"
},
"posts.comment.composer.privacy.anynomous.positive": {
"defaultMessage": "Anynomous"
},
"posts.comment.composer.privacy.anynomous.title": {
"defaultMessage": "Whether to comment as an anynomous user?"
},
"posts.comment.composer.privacy.subscribe.negative": {
"defaultMessage": "Unsubscribe"
},
"posts.comment.composer.privacy.subscribe.positive": {
"defaultMessage": "Subscribe"
},
"posts.comment.composer.privacy.subscribe.title": {
"defaultMessage": "Whether to inform you with email when receiving reply?"
},
"posts.comment.composer.privacy.visibility.negative": {
"defaultMessage": "Public"
},
"posts.comment.composer.privacy.visibility.positive": {
"defaultMessage": "Secret"
},
"posts.comment.composer.privacy.visibility.title": {
"defaultMessage": "Whether to create secret comment that only admins and peoples mentioned can see?"
},
"posts.comment.composer.submit.button": { "posts.comment.composer.submit.button": {
"defaultMessage": "Submit" "defaultMessage": "Submit"
}, },
"posts.comment.composer.tips.markdownSupported": { "posts.comment.composer.toolkits.emoji.tooltip": {
"defaultMessage": "Markdown Supported" "defaultMessage": "Insert emoji"
},
"posts.comment.composer.toolkits.image.tooltip": {
"defaultMessage": "Attach image"
},
"posts.comment.composer.toolkits.markdown.tooltip": {
"defaultMessage": "'<a href=\"https://guides.github.com/features/mastering-markdown/\" target=\"_blank\">Markdown</a>' supported"
},
"posts.comment.composer.toolkits.preview.tooltip": {
"defaultMessage": "'<i class=\"fab fa-markdown\"></i>' Markdown preview"
},
"posts.comment.composer.toolkits.privacy.tooltip": {
"defaultMessage": "Privacy settings"
}, },
"posts.commentCount": { "posts.commentCount": {
"defaultMessage": "{commentCount, plural, =0 {No comment} =1 {One comment} other {{commentCount, number, ::compact-short} Comments}}" "defaultMessage": "{commentCount, plural, =0 {No comment} =1 {One comment} other {{commentCount, number, ::compact-short} Comments}}"