mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-11-27 17:00:54 +01:00
Fixed backward compatibility for localization
This commit is contained in:
parent
c1e541b32b
commit
9c3134750e
@ -1,3 +1,8 @@
|
||||
mkdocs-material-1.11.0 (2017-10-19)
|
||||
|
||||
* Added localization to clipboard
|
||||
* Refactored i18n localization logic
|
||||
|
||||
mkdocs-material-1.10.4 (2017-10-18)
|
||||
|
||||
* Improved print styles of code blocks
|
||||
|
@ -386,6 +386,8 @@ macro `t`:
|
||||
``` jinja
|
||||
{% macro t(key) %}{{ {
|
||||
"language": "en",
|
||||
"clipboard.copy": "Copy to clipboard",
|
||||
"clipboard.copied": "Copied to clipboard",
|
||||
"edit.link.title": "Edit this page",
|
||||
"footer.previous": "Previous",
|
||||
"footer.next": "Next",
|
||||
|
@ -12,11 +12,16 @@ To determine the currently installed version, use the following command:
|
||||
|
||||
``` sh
|
||||
pip show mkdocs-material | grep -E ^Version
|
||||
# Version 1.10.4
|
||||
# Version 1.11.0
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
### 1.11.0 <small>_ October 19, 2017</small>
|
||||
|
||||
* Added localization to clipboard
|
||||
* Refactored i18n localization logic
|
||||
|
||||
### 1.10.4 <small>_ October 18, 2017</small>
|
||||
|
||||
* Improved print styles of code blocks
|
||||
|
@ -10,6 +10,8 @@ The translations can be changed in `theme/partials/language.html`:
|
||||
``` jinja
|
||||
{% macro t(key) %}{{ {
|
||||
"language": "de",
|
||||
"clipboard.copy": "In Zwischenablage kopieren",
|
||||
"clipboard.copied": "In Zwischenablage kopiert",
|
||||
"edit.link.title": "Seite editieren",
|
||||
"footer.previous": "Vorherige Seite",
|
||||
"footer.next": "Nächste Seite",
|
||||
|
@ -23,6 +23,8 @@
|
||||
<!-- Translations -->
|
||||
{% macro t(key) %}{{ {
|
||||
"language": "de",
|
||||
"clipboard.copy": "In Zwischenablage kopieren",
|
||||
"clipboard.copied": "In Zwischenablage kopiert",
|
||||
"edit.link.title": "Seite editieren",
|
||||
"footer.previous": "Vorherige Seite",
|
||||
"footer.next": "Nächste Seite",
|
||||
|
1
material/assets/javascripts/application-268d62d82d.js
Normal file
1
material/assets/javascripts/application-268d62d82d.js
Normal file
File diff suppressed because one or more lines are too long
@ -20,22 +20,22 @@
|
||||
<meta name="author" content="{{ config.site_author }}">
|
||||
{% endif %}
|
||||
{% for key in [
|
||||
"clipboard-copy",
|
||||
"clipboard-copied",
|
||||
"search-languages",
|
||||
"search-result-none",
|
||||
"search-result-one",
|
||||
"search-result-other",
|
||||
"search-tokenizer"
|
||||
"clipboard.copy",
|
||||
"clipboard.copied",
|
||||
"search.languages",
|
||||
"search.result.none",
|
||||
"search.result.one",
|
||||
"search.result.other",
|
||||
"search.tokenizer"
|
||||
] %}
|
||||
<meta name="i18n-{{ key }}" content="{{ lang.t(key) }}">
|
||||
<meta name="lang:{{ key }}" content="{{ lang.t(key) }}">
|
||||
{% endfor %}
|
||||
{% if config.site_favicon %}
|
||||
<link rel="shortcut icon" href="{{ base_url }}/{{ config.site_favicon }}">
|
||||
{% else %}
|
||||
<link rel="shortcut icon" href="{{ base_url }}/assets/images/favicon.png">
|
||||
{% endif %}
|
||||
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-1.10.4">
|
||||
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-1.11.0">
|
||||
{% endblock %}
|
||||
{% block htmltitle %}
|
||||
{% if page and page.meta.title %}
|
||||
@ -131,7 +131,7 @@
|
||||
<article class="md-content__inner md-typeset">
|
||||
{% block content %}
|
||||
{% if config.edit_uri %}
|
||||
<a href="{{ page.edit_url }}" title="{{ lang.t('edit-link-title') }}" class="md-icon md-content__icon"></a>
|
||||
<a href="{{ page.edit_url }}" title="{{ lang.t('edit.link.title') }}" class="md-icon md-content__icon"></a>
|
||||
{% endif %}
|
||||
{% if not "\x3ch1" in page.content %}
|
||||
<h1>{{ page.title | default(config.site_name, true)}}</h1>
|
||||
@ -139,7 +139,7 @@
|
||||
{{ page.content }}
|
||||
{% block source %}
|
||||
{% if page.meta.source %}
|
||||
<h2 id="__source">{{ lang.t("meta-source") }}</h2>
|
||||
<h2 id="__source">{{ lang.t("meta.source") }}</h2>
|
||||
{% set path = (page.meta.path | default([""]) | first) %}
|
||||
{% for file in page.meta.source %}
|
||||
<a href="{{ [config.repo_url, path, file] | join('/') }}" title="{{ file }}" class="md-source-file">
|
||||
@ -151,7 +151,7 @@
|
||||
{% endblock %}
|
||||
{% block disqus %}
|
||||
{% if config.extra.disqus and not page.is_homepage %}
|
||||
<h2 id="__comments">{{ lang.t("meta-comments") }}</h2>
|
||||
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
||||
{% include "partials/disqus.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@ -164,8 +164,8 @@
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% block scripts %}
|
||||
<script src="{{ base_url }}/assets/javascripts/application-ff1c1336b6.js"></script>
|
||||
{% set languages = lang.t("search-languages").split(",") %}
|
||||
<script src="{{ base_url }}/assets/javascripts/application-268d62d82d.js"></script>
|
||||
{% set languages = lang.t("search.languages").split(",") %}
|
||||
{% if languages | length and languages[0] != "" %}
|
||||
{% set path = base_url + "/assets/javascripts/lunr" %}
|
||||
<script src="{{ path }}/lunr.stemmer.support.js"></script>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
||||
<span class="md-flex__ellipsis">
|
||||
<span class="md-footer-nav__direction">
|
||||
{{ lang.t("footer-previous") }}
|
||||
{{ lang.t("footer.previous") }}
|
||||
</span>
|
||||
{{ page.previous_page.title }}
|
||||
</span>
|
||||
@ -23,7 +23,7 @@
|
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
||||
<span class="md-flex__ellipsis">
|
||||
<span class="md-footer-nav__direction">
|
||||
{{ lang.t("footer-next") }}
|
||||
{{ lang.t("footer.next") }}
|
||||
</span>
|
||||
{{ page.next_page.title }}
|
||||
</span>
|
||||
|
@ -1,19 +1,19 @@
|
||||
{% macro t(key) %}{{ {
|
||||
"language": "en",
|
||||
"clipboard-copy": "Copy to clipboard",
|
||||
"clipboard-copied": "Copied to clipboard",
|
||||
"edit-link-title": "Edit this page",
|
||||
"footer-previous": "Previous",
|
||||
"footer-next": "Next",
|
||||
"meta-comments": "Comments",
|
||||
"meta-source": "Source",
|
||||
"search-languages": "",
|
||||
"search-placeholder": "Search",
|
||||
"search-result-placeholder": "Type to start searching",
|
||||
"search-result-none": "No matching documents",
|
||||
"search-result-one": "1 matching document",
|
||||
"search-result-other": "# matching documents",
|
||||
"search-tokenizer": "[\s\-]+",
|
||||
"source-link-title": "Go to repository",
|
||||
"toc-title": "Table of contents"
|
||||
"clipboard.copy": "Copy to clipboard",
|
||||
"clipboard.copied": "Copied to clipboard",
|
||||
"edit.link.title": "Edit this page",
|
||||
"footer.previous": "Previous",
|
||||
"footer.next": "Next",
|
||||
"meta.comments": "Comments",
|
||||
"meta.source": "Source",
|
||||
"search.languages": "",
|
||||
"search.placeholder": "Search",
|
||||
"search.result.placeholder": "Type to start searching",
|
||||
"search.result.none": "No matching documents",
|
||||
"search.result.one": "1 matching document",
|
||||
"search.result.other": "# matching documents",
|
||||
"search.tokenizer": "[\s\-]+",
|
||||
"source.link.title": "Go to repository",
|
||||
"toc.title": "Table of contents"
|
||||
}[key] }}{% endmacro %}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<label class="md-search__overlay" for="search"></label>
|
||||
<div class="md-search__inner">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" required placeholder="{{ lang.t('search-placeholder') }}" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query">
|
||||
<input type="text" class="md-search__input" name="query" required placeholder="{{ lang.t('search.placeholder') }}" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query">
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset"></button>
|
||||
</form>
|
||||
@ -11,7 +11,7 @@
|
||||
<div class="md-search__scrollwrap" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="result">
|
||||
<div class="md-search-result__meta">
|
||||
{{ lang.t("search-result-placeholder") }}
|
||||
{{ lang.t("search.result.placeholder") }}
|
||||
</div>
|
||||
<ol class="md-search-result__list"></ol>
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@
|
||||
{% set repo_type = "" %}
|
||||
{% endif %}
|
||||
{% block repo %}
|
||||
<a href="{{ config.repo_url }}" title="{{ lang.t('source-link-title') }}" class="md-source" data-md-source="{{ repo_type }}">
|
||||
<a href="{{ config.repo_url }}" title="{{ lang.t('source.link.title') }}" class="md-source" data-md-source="{{ repo_type }}">
|
||||
{% if repo_type %}
|
||||
<div class="md-source__icon">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
|
@ -5,22 +5,22 @@
|
||||
{% set toc_ = (toc_ | first).children %}
|
||||
{% endif %}
|
||||
{% if toc_ | first is defined %}
|
||||
<label class="md-nav__title" for="toc">{{ lang.t("toc-title") }}</label>
|
||||
<label class="md-nav__title" for="toc">{{ lang.t("toc.title") }}</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
{% for toc_item in toc_ %}
|
||||
{% include "partials/toc-item.html" %}
|
||||
{% endfor %}
|
||||
{% if page.meta.source and page.meta.source | length > 0 %}
|
||||
<li class="md-nav__item">
|
||||
<a href="#__source" title="{{ lang.t('meta-source') }}" class="md-nav__link md-nav__link--active">
|
||||
{{ lang.t("meta-source") }}
|
||||
<a href="#__source" title="{{ lang.t('meta.source') }}" class="md-nav__link md-nav__link--active">
|
||||
{{ lang.t("meta.source") }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if config.extra.disqus and not page.is_homepage %}
|
||||
<li class="md-nav__item">
|
||||
<a href="#__comments" title="{{ lang.t('meta-comments') }}" class="md-nav__link md-nav__link--active">
|
||||
{{ lang.t("meta-comments") }}
|
||||
<a href="#__comments" title="{{ lang.t('meta.comments') }}" class="md-nav__link md-nav__link--active">
|
||||
{{ lang.t("meta.comments") }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mkdocs-material",
|
||||
"version": "1.10.4",
|
||||
"version": "1.11.0",
|
||||
"description": "A Material Design theme for MkDocs",
|
||||
"keywords": [
|
||||
"mkdocs",
|
||||
|
@ -37,8 +37,8 @@ import Material from "./components/Material"
|
||||
*
|
||||
* @return {string} Meta content value
|
||||
*/
|
||||
const i18n = (key, _) => { // eslint-disable-line no-unused-vars
|
||||
const meta = document.querySelector(`[name=i18n-${key}]`)
|
||||
const translate = (key, _) => { // eslint-disable-line no-unused-vars
|
||||
const meta = document.getElementsByName(`lang:${key}`)[0]
|
||||
if (!(meta instanceof HTMLMetaElement))
|
||||
throw new ReferenceError
|
||||
return meta.content
|
||||
@ -92,7 +92,7 @@ function initialize(config) { // eslint-disable-line func-style
|
||||
|
||||
/* Create button with message container */
|
||||
const button = (
|
||||
<button class="md-clipboard" title={i18n("clipboard-copy")}
|
||||
<button class="md-clipboard" title={translate("clipboard.copy")}
|
||||
data-clipboard-target={`#${id} pre, #${id} code`}>
|
||||
<span class="md-clipboard__message"></span>
|
||||
</button>
|
||||
@ -120,7 +120,7 @@ function initialize(config) { // eslint-disable-line func-style
|
||||
|
||||
/* Set message indicating success and show it */
|
||||
message.classList.add("md-clipboard__message--active")
|
||||
message.innerHTML = i18n("clipboard-copied")
|
||||
message.innerHTML = translate("clipboard.copied")
|
||||
|
||||
/* Hide message after two seconds */
|
||||
message.dataset.mdTimer = setTimeout(() => {
|
||||
|
@ -55,8 +55,8 @@ const truncate = (string, n) => {
|
||||
*
|
||||
* @return {string} Meta content value
|
||||
*/
|
||||
const i18n = (key, _) => { // eslint-disable-line no-unused-vars
|
||||
const meta = document.querySelector(`[name=i18n-${key}]`)
|
||||
const translate = (key, _) => { // eslint-disable-line no-unused-vars
|
||||
const meta = document.getElementsByName(`lang:${key}`)[0]
|
||||
if (!(meta instanceof HTMLMetaElement))
|
||||
throw new ReferenceError
|
||||
return meta.content
|
||||
@ -106,18 +106,18 @@ export default class Result {
|
||||
/* Load messages for metadata display */
|
||||
this.message_ = {
|
||||
placeholder: this.meta_.textContent,
|
||||
none: i18n("search-result-none"),
|
||||
one: i18n("search-result-one"),
|
||||
other: i18n("search-result-other")
|
||||
none: translate("search.result.none"),
|
||||
one: translate("search.result.one"),
|
||||
other: translate("search.result.other")
|
||||
}
|
||||
|
||||
/* Override tokenizer separator, if given */
|
||||
const tokenizer = i18n("search-tokenizer")
|
||||
const tokenizer = translate("search.tokenizer")
|
||||
if (tokenizer.length)
|
||||
lunr.tokenizer.separator = tokenizer
|
||||
|
||||
/* Load search languages */
|
||||
this.lang_ = i18n("search-languages").split(",")
|
||||
this.lang_ = translate("search.languages").split(",")
|
||||
.filter(Boolean)
|
||||
.map(lang => lang.trim())
|
||||
}
|
||||
|
@ -56,15 +56,15 @@
|
||||
|
||||
<!-- Localization -->
|
||||
{% for key in [
|
||||
"clipboard-copy",
|
||||
"clipboard-copied",
|
||||
"search-languages",
|
||||
"search-result-none",
|
||||
"search-result-one",
|
||||
"search-result-other",
|
||||
"search-tokenizer"
|
||||
"clipboard.copy",
|
||||
"clipboard.copied",
|
||||
"search.languages",
|
||||
"search.result.none",
|
||||
"search.result.one",
|
||||
"search.result.other",
|
||||
"search.tokenizer"
|
||||
] %}
|
||||
<meta name="i18n-{{ key }}" content="{{ lang.t(key) }}" />
|
||||
<meta name="lang:{{ key }}" content="{{ lang.t(key) }}" />
|
||||
{% endfor %}
|
||||
|
||||
<!-- Favicon -->
|
||||
@ -247,7 +247,7 @@
|
||||
<!-- Edit button, if URL was defined -->
|
||||
{% if config.edit_uri %}
|
||||
<a href="{{ page.edit_url }}"
|
||||
title="{{ lang.t('edit-link-title') }}"
|
||||
title="{{ lang.t('edit.link.title') }}"
|
||||
class="md-icon md-content__icon"><!-- edit --></a>
|
||||
{% endif %}
|
||||
|
||||
@ -266,7 +266,7 @@
|
||||
<!-- Source files -->
|
||||
{% block source %}
|
||||
{% if page.meta.source %}
|
||||
<h2 id="__source">{{ lang.t("meta-source") }}</h2>
|
||||
<h2 id="__source">{{ lang.t("meta.source") }}</h2>
|
||||
{% set path = (page.meta.path | default([""]) | first) %}
|
||||
{% for file in page.meta.source %}
|
||||
<a href="{{ [config.repo_url, path, file] | join('/') }}"
|
||||
@ -281,7 +281,7 @@
|
||||
<!-- Disqus integration -->
|
||||
{% block disqus %}
|
||||
{% if config.extra.disqus and not page.is_homepage %}
|
||||
<h2 id="__comments">{{ lang.t("meta-comments") }}</h2>
|
||||
<h2 id="__comments">{{ lang.t("meta.comments") }}</h2>
|
||||
{% include "partials/disqus.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@ -301,7 +301,7 @@
|
||||
<script src="{{ base_url }}/assets/javascripts/application.js"></script>
|
||||
|
||||
<!-- Load additional languages for search -->
|
||||
{% set languages = lang.t("search-languages").split(",") %}
|
||||
{% set languages = lang.t("search.languages").split(",") %}
|
||||
{% if languages | length and languages[0] != "" %}
|
||||
{% set path = base_url + "/assets/javascripts/lunr" %}
|
||||
<script src="{{ path }}/lunr.stemmer.support.js"></script>
|
||||
|
@ -44,7 +44,7 @@
|
||||
md-footer-nav__title">
|
||||
<span class="md-flex__ellipsis">
|
||||
<span class="md-footer-nav__direction">
|
||||
{{ lang.t("footer-previous") }}
|
||||
{{ lang.t("footer.previous") }}
|
||||
</span>
|
||||
{{ page.previous_page.title }}
|
||||
</span>
|
||||
@ -61,7 +61,7 @@
|
||||
md-footer-nav__title">
|
||||
<span class="md-flex__ellipsis">
|
||||
<span class="md-footer-nav__direction">
|
||||
{{ lang.t("footer-next") }}
|
||||
{{ lang.t("footer.next") }}
|
||||
</span>
|
||||
{{ page.next_page.title }}
|
||||
</span>
|
||||
|
@ -23,20 +23,20 @@
|
||||
<!-- Translations -->
|
||||
{% macro t(key) %}{{ {
|
||||
"language": "en",
|
||||
"clipboard-copy": "Copy to clipboard",
|
||||
"clipboard-copied": "Copied to clipboard",
|
||||
"edit-link-title": "Edit this page",
|
||||
"footer-previous": "Previous",
|
||||
"footer-next": "Next",
|
||||
"meta-comments": "Comments",
|
||||
"meta-source": "Source",
|
||||
"search-languages": "",
|
||||
"search-placeholder": "Search",
|
||||
"search-result-placeholder": "Type to start searching",
|
||||
"search-result-none": "No matching documents",
|
||||
"search-result-one": "1 matching document",
|
||||
"search-result-other": "# matching documents",
|
||||
"search-tokenizer": "[\s\-]+",
|
||||
"source-link-title": "Go to repository",
|
||||
"toc-title": "Table of contents"
|
||||
"clipboard.copy": "Copy to clipboard",
|
||||
"clipboard.copied": "Copied to clipboard",
|
||||
"edit.link.title": "Edit this page",
|
||||
"footer.previous": "Previous",
|
||||
"footer.next": "Next",
|
||||
"meta.comments": "Comments",
|
||||
"meta.source": "Source",
|
||||
"search.languages": "",
|
||||
"search.placeholder": "Search",
|
||||
"search.result.placeholder": "Type to start searching",
|
||||
"search.result.none": "No matching documents",
|
||||
"search.result.one": "1 matching document",
|
||||
"search.result.other": "# matching documents",
|
||||
"search.tokenizer": "[\s\-]+",
|
||||
"source.link.title": "Go to repository",
|
||||
"toc.title": "Table of contents"
|
||||
}[key] }}{% endmacro %}
|
||||
|
@ -28,7 +28,7 @@
|
||||
<div class="md-search__inner">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query"
|
||||
required placeholder="{{ lang.t('search-placeholder') }}"
|
||||
required placeholder="{{ lang.t('search.placeholder') }}"
|
||||
autocapitalize="off" autocorrect="off" autocomplete="off"
|
||||
spellcheck="false" data-md-component="query" />
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
@ -39,7 +39,7 @@
|
||||
<div class="md-search__scrollwrap" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="result">
|
||||
<div class="md-search-result__meta">
|
||||
{{ lang.t("search-result-placeholder") }}
|
||||
{{ lang.t("search.result.placeholder") }}
|
||||
</div>
|
||||
<ol class="md-search-result__list"></ol>
|
||||
</div>
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
<!-- Repository containing source -->
|
||||
{% block repo %}
|
||||
<a href="{{ config.repo_url }}" title="{{ lang.t('source-link-title') }}"
|
||||
<a href="{{ config.repo_url }}" title="{{ lang.t('source.link.title') }}"
|
||||
class="md-source" data-md-source="{{ repo_type }}">
|
||||
{% if repo_type %}
|
||||
<div class="md-source__icon">
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
<!-- Render item list -->
|
||||
{% if toc_ | first is defined %}
|
||||
<label class="md-nav__title" for="toc">{{ lang.t("toc-title") }}</label>
|
||||
<label class="md-nav__title" for="toc">{{ lang.t("toc.title") }}</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
{% for toc_item in toc_ %}
|
||||
{% include "partials/toc-item.html" %}
|
||||
@ -47,9 +47,9 @@
|
||||
<!-- Source files -->
|
||||
{% if page.meta.source and page.meta.source | length > 0 %}
|
||||
<li class="md-nav__item">
|
||||
<a href="#__source" title="{{ lang.t('meta-source') }}"
|
||||
<a href="#__source" title="{{ lang.t('meta.source') }}"
|
||||
class="md-nav__link md-nav__link--active">
|
||||
{{ lang.t("meta-source") }}
|
||||
{{ lang.t("meta.source") }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
@ -57,9 +57,9 @@
|
||||
<!-- Disqus integration -->
|
||||
{% if config.extra.disqus and not page.is_homepage %}
|
||||
<li class="md-nav__item">
|
||||
<a href="#__comments" title="{{ lang.t('meta-comments') }}"
|
||||
<a href="#__comments" title="{{ lang.t('meta.comments') }}"
|
||||
class="md-nav__link md-nav__link--active">
|
||||
{{ lang.t("meta-comments") }}
|
||||
{{ lang.t("meta.comments") }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
Loading…
Reference in New Issue
Block a user