feat(native): devices page — 2-line entries, single UIMenu CTA, dynamic counter, slimmer buttons
- MobileDeviceRow: collapse to 2 lines (name+badge / lastSeen · seit date) - ProtectedDeviceRow: collapse to 2 lines (name+badge / seit date or degraded hint) - Both rows now use alignItems:center for visual parity - Replace dual Mac/Windows buttons with single UIMenu "+ neues Gerät hinzufügen" - MenuView disabled (no-op TouchableOpacity) when at device limit - Dynamic counter below subtitle: "X von 3 Geräten · noch Y frei" / "Maximum erreicht" - paddingVertical 16→12 on all primary CTAs in devices.tsx, AddMacSheet, AddWindowsSheet - New i18n keys: devices.add_device, devices.counter_some, devices.counter_limit (DE/EN/FR) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8851f36f65
commit
e8ea00568e
@ -132,11 +132,14 @@ function MobileDeviceRow({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deviceName = device.model ?? device.name ?? device.platform;
|
||||||
|
const footerText = `${formatLastSeen(device.lastSeenAt, t)} · ${t('settings.devices_since')} ${formatSince(device.createdAt)}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'center',
|
||||||
gap: 12,
|
gap: 12,
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
paddingVertical: 14,
|
paddingVertical: 14,
|
||||||
@ -166,7 +169,7 @@ function MobileDeviceRow({
|
|||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{device.name ?? device.model ?? device.platform}
|
{deviceName}
|
||||||
</Text>
|
</Text>
|
||||||
{device.isCurrent ? (
|
{device.isCurrent ? (
|
||||||
<View
|
<View
|
||||||
@ -190,37 +193,17 @@ function MobileDeviceRow({
|
|||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{device.model && device.name && !device.name.includes(device.model) ? (
|
<Text
|
||||||
<Text
|
numberOfLines={1}
|
||||||
style={{
|
style={{
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: colors.textMuted,
|
color: colors.textMuted,
|
||||||
fontFamily: 'Nunito_400Regular',
|
fontFamily: 'Nunito_400Regular',
|
||||||
marginTop: 1,
|
marginTop: 3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{device.model}
|
{footerText}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
|
||||||
|
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12, marginTop: 4 }}>
|
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
|
|
||||||
<Ionicons name="time-outline" size={11} color={colors.textMuted} />
|
|
||||||
<Text
|
|
||||||
style={{ fontSize: 11, color: colors.textMuted, fontFamily: 'Nunito_400Regular' }}
|
|
||||||
>
|
|
||||||
{formatLastSeen(device.lastSeenAt, t)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
|
|
||||||
<Ionicons name="link-outline" size={11} color={colors.textMuted} />
|
|
||||||
<Text
|
|
||||||
style={{ fontSize: 11, color: colors.textMuted, fontFamily: 'Nunito_400Regular' }}
|
|
||||||
>
|
|
||||||
{t('settings.devices_since')} {formatSince(device.createdAt)}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{!device.isCurrent ? (
|
{!device.isCurrent ? (
|
||||||
@ -277,7 +260,7 @@ function ProtectedDeviceRow({
|
|||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'center',
|
||||||
gap: 12,
|
gap: 12,
|
||||||
paddingHorizontal: 14,
|
paddingHorizontal: 14,
|
||||||
paddingVertical: 14,
|
paddingVertical: 14,
|
||||||
@ -297,7 +280,7 @@ function ProtectedDeviceRow({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={{ flex: 1, minWidth: 0 }}>
|
<View style={{ flex: 1, minWidth: 0 }}>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={{
|
style={{
|
||||||
@ -312,26 +295,19 @@ function ProtectedDeviceRow({
|
|||||||
<StatusBadge status={device.status} />
|
<StatusBadge status={device.status} />
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 4, marginTop: 4 }}>
|
<Text
|
||||||
<Ionicons name="link-outline" size={11} color={colors.textMuted} />
|
numberOfLines={1}
|
||||||
<Text style={{ fontSize: 11, color: colors.textMuted, fontFamily: 'Nunito_400Regular' }}>
|
style={{
|
||||||
{t('settings.devices_since')} {formatSince(device.createdAt)}
|
fontSize: 11,
|
||||||
</Text>
|
color: device.status === 'degraded' ? colors.error : colors.textMuted,
|
||||||
</View>
|
fontFamily: 'Nunito_400Regular',
|
||||||
|
marginTop: 3,
|
||||||
{device.status === 'degraded' && (
|
}}
|
||||||
<Text
|
>
|
||||||
style={{
|
{device.status === 'degraded'
|
||||||
fontSize: 11,
|
? t('plan_limit.device_degraded_body')
|
||||||
color: colors.error,
|
: `${t('settings.devices_since')} ${formatSince(device.createdAt)}`}
|
||||||
fontFamily: 'Nunito_400Regular',
|
</Text>
|
||||||
marginTop: 4,
|
|
||||||
lineHeight: 15,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t('plan_limit.device_degraded_body')}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<MenuView
|
<MenuView
|
||||||
@ -426,12 +402,24 @@ export default function DevicesScreen() {
|
|||||||
useProtectedDevicesRealtime();
|
useProtectedDevicesRealtime();
|
||||||
|
|
||||||
const MAX_PROTECTED_DEVICES = 2;
|
const MAX_PROTECTED_DEVICES = 2;
|
||||||
|
const TOTAL_DEVICE_SLOTS = 3;
|
||||||
const activeProtectedCount = protectedDevices.filter((d) => d.status !== 'revoked').length;
|
const activeProtectedCount = protectedDevices.filter((d) => d.status !== 'revoked').length;
|
||||||
|
const totalRegistered = 1 + activeProtectedCount;
|
||||||
const atDeviceLimit = isLegend && activeProtectedCount >= MAX_PROTECTED_DEVICES;
|
const atDeviceLimit = isLegend && activeProtectedCount >= MAX_PROTECTED_DEVICES;
|
||||||
|
|
||||||
const currentDevice = mobileDevices.find((d) => d.isCurrent);
|
const currentDevice = mobileDevices.find((d) => d.isCurrent);
|
||||||
const subtitle = isLegend ? t('devices.subtitle_legend') : t('devices.subtitle_free');
|
const subtitle = isLegend ? t('devices.subtitle_legend') : t('devices.subtitle_free');
|
||||||
|
|
||||||
|
const counterText = isLegend
|
||||||
|
? atDeviceLimit
|
||||||
|
? t('devices.counter_limit', { max: TOTAL_DEVICE_SLOTS })
|
||||||
|
: t('devices.counter_some', {
|
||||||
|
count: totalRegistered,
|
||||||
|
max: TOTAL_DEVICE_SLOTS,
|
||||||
|
remaining: TOTAL_DEVICE_SLOTS - totalRegistered,
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
async function handleRemoveProtected(id: string) {
|
async function handleRemoveProtected(id: string) {
|
||||||
try {
|
try {
|
||||||
const { manualRemovalRequired } = await removeProtected(id);
|
const { manualRemovalRequired } = await removeProtected(id);
|
||||||
@ -457,18 +445,30 @@ export default function DevicesScreen() {
|
|||||||
}}
|
}}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
>
|
>
|
||||||
{/* Subtitle */}
|
{/* Subtitle + counter */}
|
||||||
<Text
|
<View style={{ gap: 4, marginBottom: -12 }}>
|
||||||
style={{
|
<Text
|
||||||
fontSize: 13,
|
style={{
|
||||||
color: colors.textMuted,
|
fontSize: 13,
|
||||||
fontFamily: 'Nunito_400Regular',
|
color: colors.textMuted,
|
||||||
lineHeight: 18,
|
fontFamily: 'Nunito_400Regular',
|
||||||
marginBottom: -12,
|
lineHeight: 18,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</Text>
|
</Text>
|
||||||
|
{counterText ? (
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 12,
|
||||||
|
color: atDeviceLimit ? colors.brandOrange : colors.textMuted,
|
||||||
|
fontFamily: 'Nunito_600SemiBold',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{counterText}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
|
||||||
{/* Section 1: Dieses Gerät */}
|
{/* Section 1: Dieses Gerät */}
|
||||||
<View>
|
<View>
|
||||||
@ -539,80 +539,57 @@ export default function DevicesScreen() {
|
|||||||
|
|
||||||
{/* CTA or Upgrade */}
|
{/* CTA or Upgrade */}
|
||||||
{isLegend ? (
|
{isLegend ? (
|
||||||
<View style={{ gap: 10 }}>
|
atDeviceLimit ? (
|
||||||
{atDeviceLimit && (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
backgroundColor: colors.surfaceElevated,
|
|
||||||
borderRadius: 12,
|
|
||||||
padding: 12,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: colors.border,
|
|
||||||
flexDirection: 'row',
|
|
||||||
gap: 8,
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Ionicons name="information-circle-outline" size={16} color={colors.textMuted} style={{ marginTop: 1 }} />
|
|
||||||
<Text style={{ flex: 1, fontSize: 13, color: colors.textMuted, fontFamily: 'Nunito_400Regular', lineHeight: 18 }}>
|
|
||||||
{t('plan_limit.device_add_limit_hint', { max: MAX_PROTECTED_DEVICES })}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => {
|
activeOpacity={1}
|
||||||
if (atDeviceLimit) {
|
style={{
|
||||||
Alert.alert(t('plan_limit.device_add_limit_short'), t('plan_limit.device_add_limit_hint', { max: MAX_PROTECTED_DEVICES }));
|
backgroundColor: colors.surfaceElevated,
|
||||||
return;
|
borderRadius: 14,
|
||||||
}
|
paddingVertical: 12,
|
||||||
setAddMacVisible(true);
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: 8,
|
||||||
|
opacity: 0.5,
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="add-circle-outline" size={20} color={colors.textMuted} />
|
||||||
|
<Text style={{ fontSize: 16, color: colors.textMuted, fontFamily: 'Nunito_700Bold' }}>
|
||||||
|
{t('devices.add_device')}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
) : (
|
||||||
|
<MenuView
|
||||||
|
title={t('devices.add_device')}
|
||||||
|
actions={[
|
||||||
|
{ id: 'mac', title: 'Mac' },
|
||||||
|
{ id: 'windows', title: 'Windows-PC' },
|
||||||
|
]}
|
||||||
|
onPressAction={({ nativeEvent: { event } }) => {
|
||||||
|
if (event === 'mac') setAddMacVisible(true);
|
||||||
|
else if (event === 'windows') setAddWindowsVisible(true);
|
||||||
|
}}
|
||||||
|
shouldOpenOnLongPress={false}
|
||||||
|
>
|
||||||
|
<TouchableOpacity
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: atDeviceLimit ? colors.surfaceElevated : colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
gap: 8,
|
gap: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Ionicons name="add-circle-outline" size={20} color={atDeviceLimit ? colors.textMuted : '#fff'} />
|
<Ionicons name="add-circle-outline" size={20} color="#fff" />
|
||||||
<Text style={{ fontSize: 16, color: atDeviceLimit ? colors.textMuted : '#fff', fontFamily: 'Nunito_700Bold' }}>
|
<Text style={{ fontSize: 16, color: '#fff', fontFamily: 'Nunito_700Bold' }}>
|
||||||
{t('devices.add_mac')}
|
{t('devices.add_device')}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
</MenuView>
|
||||||
<TouchableOpacity
|
)
|
||||||
onPress={() => {
|
|
||||||
if (atDeviceLimit) {
|
|
||||||
Alert.alert(t('plan_limit.device_add_limit_short'), t('plan_limit.device_add_limit_hint', { max: MAX_PROTECTED_DEVICES }));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setAddWindowsVisible(true);
|
|
||||||
}}
|
|
||||||
activeOpacity={0.7}
|
|
||||||
style={{
|
|
||||||
borderRadius: 14,
|
|
||||||
paddingVertical: 14,
|
|
||||||
alignItems: 'center',
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'center',
|
|
||||||
gap: 8,
|
|
||||||
backgroundColor: colors.surface,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: colors.border,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Ionicons name="desktop-outline" size={18} color={colors.textMuted} />
|
|
||||||
<Text
|
|
||||||
style={{ fontSize: 14, color: colors.textMuted, fontFamily: 'Nunito_600SemiBold' }}
|
|
||||||
>
|
|
||||||
{t('devices.add_windows_enabled')}
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
) : (
|
) : (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@ -637,7 +614,7 @@ export default function DevicesScreen() {
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
paddingVertical: 14,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -204,7 +204,7 @@ function Step1LabelContent({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
opacity: enrolling ? 0.7 : 1,
|
opacity: enrolling ? 0.7 : 1,
|
||||||
}}
|
}}
|
||||||
@ -314,7 +314,7 @@ function Step2OnboardingContent({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
@ -430,7 +430,7 @@ function Step3SuccessContent({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
paddingHorizontal: 40,
|
paddingHorizontal: 40,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
alignSelf: 'stretch',
|
alignSelf: 'stretch',
|
||||||
|
|||||||
@ -212,7 +212,7 @@ function WindowsStep1LabelContent({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
opacity: enrolling ? 0.7 : 1,
|
opacity: enrolling ? 0.7 : 1,
|
||||||
}}
|
}}
|
||||||
@ -326,7 +326,7 @@ function WindowsStep2OnboardingContent({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
@ -348,7 +348,7 @@ function WindowsStep2OnboardingContent({
|
|||||||
borderWidth: 1.5,
|
borderWidth: 1.5,
|
||||||
borderColor: colors.brandOrange,
|
borderColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 14,
|
paddingVertical: 12,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
opacity: confirming ? 0.7 : 1,
|
opacity: confirming ? 0.7 : 1,
|
||||||
}}
|
}}
|
||||||
@ -434,7 +434,7 @@ function WindowsStep3SuccessContent({
|
|||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.brandOrange,
|
backgroundColor: colors.brandOrange,
|
||||||
borderRadius: 14,
|
borderRadius: 14,
|
||||||
paddingVertical: 16,
|
paddingVertical: 12,
|
||||||
paddingHorizontal: 40,
|
paddingHorizontal: 40,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
alignSelf: 'stretch',
|
alignSelf: 'stretch',
|
||||||
|
|||||||
@ -889,6 +889,9 @@
|
|||||||
"success_body": "Du kannst weitere Geräte hinzufügen wenn du willst.",
|
"success_body": "Du kannst weitere Geräte hinzufügen wenn du willst.",
|
||||||
"remove_warning_title": "Profile manuell entfernen",
|
"remove_warning_title": "Profile manuell entfernen",
|
||||||
"remove_warning_body": "Wir können das Profile nicht aus der Ferne löschen. Auf dem Mac: Systemeinstellungen → Profile → ReBreak → Entfernen (Admin-Passwort nötig).",
|
"remove_warning_body": "Wir können das Profile nicht aus der Ferne löschen. Auf dem Mac: Systemeinstellungen → Profile → ReBreak → Entfernen (Admin-Passwort nötig).",
|
||||||
|
"add_device": "+ neues Gerät hinzufügen",
|
||||||
|
"counter_some": "{{count}} von {{max}} Geräten · noch {{remaining}} frei",
|
||||||
|
"counter_limit": "Maximum erreicht — {{max}} von {{max}} Geräten",
|
||||||
"add_windows_enabled": "Windows-PC hinzufügen",
|
"add_windows_enabled": "Windows-PC hinzufügen",
|
||||||
"windows_label_question": "Wie soll der Windows-PC heißen?",
|
"windows_label_question": "Wie soll der Windows-PC heißen?",
|
||||||
"windows_label_default": "Windows-PC",
|
"windows_label_default": "Windows-PC",
|
||||||
|
|||||||
@ -889,6 +889,9 @@
|
|||||||
"success_body": "You can add more devices whenever you like.",
|
"success_body": "You can add more devices whenever you like.",
|
||||||
"remove_warning_title": "Remove profile manually",
|
"remove_warning_title": "Remove profile manually",
|
||||||
"remove_warning_body": "We can't delete the profile remotely. On the Mac: System Settings → Profiles → ReBreak → Remove (admin password required).",
|
"remove_warning_body": "We can't delete the profile remotely. On the Mac: System Settings → Profiles → ReBreak → Remove (admin password required).",
|
||||||
|
"add_device": "+ add new device",
|
||||||
|
"counter_some": "{{count}} of {{max}} devices · {{remaining}} more available",
|
||||||
|
"counter_limit": "Maximum reached — {{max}} of {{max}} devices",
|
||||||
"add_windows_enabled": "Add Windows PC",
|
"add_windows_enabled": "Add Windows PC",
|
||||||
"windows_label_question": "What should this Windows PC be called?",
|
"windows_label_question": "What should this Windows PC be called?",
|
||||||
"windows_label_default": "Windows PC",
|
"windows_label_default": "Windows PC",
|
||||||
|
|||||||
@ -886,6 +886,9 @@
|
|||||||
"success_body": "Vous pouvez ajouter d'autres appareils quand vous le souhaitez.",
|
"success_body": "Vous pouvez ajouter d'autres appareils quand vous le souhaitez.",
|
||||||
"remove_warning_title": "Supprimer le profil manuellement",
|
"remove_warning_title": "Supprimer le profil manuellement",
|
||||||
"remove_warning_body": "Nous ne pouvons pas supprimer le profil à distance. Sur le Mac : Réglages système → Profils → ReBreak → Supprimer (mot de passe administrateur requis).",
|
"remove_warning_body": "Nous ne pouvons pas supprimer le profil à distance. Sur le Mac : Réglages système → Profils → ReBreak → Supprimer (mot de passe administrateur requis).",
|
||||||
|
"add_device": "+ ajouter un appareil",
|
||||||
|
"counter_some": "{{count}} sur {{max}} appareils · encore {{remaining}} disponible",
|
||||||
|
"counter_limit": "Maximum atteint — {{max}} sur {{max}} appareils",
|
||||||
"add_windows_enabled": "Ajouter un PC Windows",
|
"add_windows_enabled": "Ajouter un PC Windows",
|
||||||
"windows_label_question": "Comment appeler ce PC Windows ?",
|
"windows_label_question": "Comment appeler ce PC Windows ?",
|
||||||
"windows_label_default": "PC Windows",
|
"windows_label_default": "PC Windows",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user